home—lects—hws
D2L—breeze (snow day)
hw02
hw02: Functions that return (html) text
Due 2016.Feb.10 (Wed) 16:00
Submit on D2L, and a bring hardcopy of your three files
utils.php,
utils-test.php,
and
silly-page.php.
The files should also be viewable on the web, as discussed below (and on Monday's lecture).
For this homework, create a directory ~/dynamic_php/itec325/hw02.
- utils.php, which contains (only) code for php functions below.
- utils-test.php, which contains only the runnable test cases for those functions.
- silly-page.php, which (when run) just prints out (what happens to be)
valid html for a web page that includes
a hyperlink,
a thumbnail image,
a comma-separated list,
and
a list of links created via table-of-contents
(all created by calling your functions).
This time, silly-page.php should be mostly not enclosed in <?php …>.
After testing that this file prints some html from the command-line,
make sure it is viewable on the web as
https://php.radford.edu/~yourUserName/itec325/hw02/silly-page.php.
(5pts) A function test : ANY, ANY → void
which determines if the first value (an actual test-result) is equal to the second value
(the desired test-result); if not the function should print a message.
We'll use this to make our testing more convenient.
For example, your utils-test.php from
hw01
could be replaced with lines like “test( pluralize(4,"cow"), "4 cows" );”.
This way, only tests that fail get printed,
and we don't need to visually scan through lots of
output about tests which pass.
Two other requirements, to make this function even more useful:
- When testing functions which return html,
it's a bit annoying if a test were to fail due only to whitespace (e.g. our
function returned two spaces where the expected-output only had one space,
or had a newline).
SO: before comparing strings,
collapse all groups of one-or-more whitespace
characters to a single space1.
(Hint: use preg_replace('/\s+/', ' ', …),
but only call it your if your two inputs
is_strings.)
You may want to also trim whitespace from the start and end of
each string.
-
Sometimes it's nice to get some small output, even when tests are passing,
so that you know that the tests really are being run at all!
Make a named-constant with define( "PRINT_ON_SUCCESS", true ).
Then, test checks this PRINT_ON_SUCCESS flag,
and prints something small (like “.”)
if it's true,
and nothing if it's false (for passing tests).
You can easily turn this behavior on/off by changing that single define.
(Be sure that test always prints something when a test fails, though!)
-
You may add further features if you like, such as keep a counter of how many tests
have been made, and then any failing-tests can include the test-number
as well as other details.
(You don't need to have test-cases for test itself;
since it's a void function that prints, it's not suitable for unit-testing.
This means you need to be extra careful to make sure it really does work
as you expect.)
- (10pts)
Write a function string hyperlink( string $url, string-or-boolean $linkTxt )
which returns a string of html.
If the provided $linkTxt is false (instead of a string),
then use the $url as the link text.
hyperlink( "http://www.gutenberg.org", "free books!" ) === "<a href='http://www.gutenberg.org'>free books!</a>"
hyperlink( "myLocalFile.html", false ) === "<a href='myLocalFile.html'>myLocalFile.html</a>"
Note that this is just a regular ol' function that takes in strings and returns strings!
The fact that the strings happen to have angle-brackets in them means that the result might
be useful to people generating html, but the function itself does't really care.
(You don't need to come up with additional test cases,
but you do need to actually include these tests or their equivalent.
You can assume that neither string is ever empty.)
Note how the input strings don't contain any quote-characters,
but the returned result does (since HTML attributes must be quoted).
I recommend that your generated html uses single quote marks around attributes,
but you'll get full credit for either single- or double-quote marks, as long as it is valid HTML.
Make sure your test case(s) express exactly what you want the desired output should be!
- (15pts) We will write a function to help us
generate thumbnails:
- What is the html element for
an image with source pony.jpg (in the same directory),
that is rendered 300px wide?
Include your answer in a comment, in your test-file.
-
What is the html for such an image which is also a link —
where the link would take you to that image
(not a html page — just that image).
Include your answer in a comment, in your test-file.
-
Make the above into a runnable
test-case for thumbnail("pony.jpg",300);
the expected-output should be a string that happened to be your answer.
You don't need further test-cases for this problem.
Pay close attention to the exact spacing you want to have.
As discussed in class,
I recommend using single-quotes (') around
the attribute-values.
-
Finally, implement the function thumbnail that takes in
a string (a URL) and a number (the width in pixels),
and returns a string that is an html link containing an image.
For full credit, your function should call hyperlink as already written!
- (20pts)
Write a function which takes in an array of strings,
and returns a single, long string:
a comma-separated list of all the individual strings,
with “and” before
the last element (if more than one)2.
The resulting string should be suitable for splicing into the middle of a paragraph of prose,
and should be proper, grammatical English.
(This function has nothing to do with html.)
Include at least three test cases, each testing a different situation.
- (20pts)
Write a function toc (“table of contents”):
It takes an array of strings, and returns a string that is
HTML for an un-ordered list of links to anchors within the same document.
For example,
given an array with
"thumbnail-problem",
"commaList-problem",
and
"due-date",
it would return HTML that would render as:
(Try clicking on those items, and feel free to view-source, to understand what it's doing.
Of course, this function is only helpful
if the strings in the array are also used as id attributes elsewhere in the page.)
For full credit, this function should involve a call to hyperlink.
-
(10pts) Make sure your files are runnable via the web at (for example)
https://php.radford.edu/~yourUserName/itec325/hw02/silly-page.php.
Notes:
-
For all assignments in this class (and for all your classes)
your primary file (utils.php in this case)
must start with a comment containing:
Your name; the class/semester; the URL of this assignment page.
-
Every function should be commented with a short (1-sentence) description,
(which mentions every parameter by name),
and should indicate the types of the parameters and the return-type.
You do not need to check for invalid-inputs to your functions.
E.g.:
if I ask for a function taking in (say) a number and a string,
and you repeat in your function-comment that your function handles a number and a string,
then you don't need to check for being given incorrect inputs —
that's the caller's problem, not yours.
Similarly for more refined types like "non-empty-string" or "integer in the range [1,12]":
if it's in the comments as a pre-condition, that'll suffice.3
(We'll talk about validating input received from the (external, untrusted) user later.)
-
Any HTML/XML for this class should follow the following common guidelines:
-
Every tag must be closed.
(Empty-tag notation is fine, but no dangling <p> open-tags.)
-
Every attribute must have a value, and it must be quoted.
-
Tags are case-sensitive.
-
Indent clearly, as for any programming class (or your non-programming classes for that matter).
We'll require these even where it's not strictly needed for (mere) HTML5 compliance.
1Why not collapse whitespace to nothing at
all?
This is tempting, since an actual&desired output of
"<ul></ul>"
and
"<ul>\n</ul>"
would then be considered okay.
However, this allows false-negatives:
getting "hit here"
when expecting
"hi there"
wouldn't register as an error.
… I guess the best of both worlds might be,
after collapsing whitespace, make another substitution which
removes any space between a "<" and a ">" only.
(Hmm, and surrounding "=" if inside a tag's attribute/value pairs?
That's much harder to exactly get right, via regular expressions.)
↩
2When having a list of more than 2 items, I personally recommend using
the Oxford comma
(or, see wikipedia)
but I will leave it to your preference. ↩
3
While the defensive-programming can be helpful in bigger projects
(esp. in untyped languages like php), it's never interesting code.
If you DO want to do the checks anyway, that's fine, but do all the type-validation
right away (before you enter the 'real' function-logic),
and throw an error if something goes wrong
(don't continue and return some sort of odd, undocumented answer).
For example:
function foo( $someNum ) {
// optional error-check:
if !(is_numeric($someNum)) { throw new InvalidArgumentException( 'foo: expected number, given ' . $someNum ); }
// ...now put your real code, uncluttered by further type-checks.
}
|
(Ideally, you'd include the type-requirements in comments,
and then a tool would automatically generate the above boilerplate error-checking for you.
That's what Java's type-system gives you, for example.)
↩
home—lects—hws
D2L—breeze (snow day)