Source Code for /public/inc/searchindex.json
[
{
"url": "\/footer.php",
"kind": "code",
"title": "footer.php",
"body": "<\/main>\r\n\r\n <footer>\r\n <ul>\r\n <li>\r\n an\r\n <a href=\"https:\/\/github.com\/dan-q\/php-cookery-class\">open source<\/a>\r\n project\r\n <\/li>\r\n <li>\r\n by\r\n <a href=\"https:\/\/www.danq.me\/\">Dan Q<\/a>\r\n <\/li>\r\n <li>\r\n <a href=\"\/source-viewer.php?file=public\/<?php echo $_SERVER['SCRIPT_NAME']; ?>\">view PHP source of <em>this page<\/em>!<\/a>\r\n <\/li>\r\n <\/ul>\r\n <\/footer>\r\n <\/div>\r\n<\/body>\r\n<\/html>"
},
{
"url": "\/functions.php",
"kind": "code",
"title": "functions.php",
"body": "<?php\r\n\/\/ Load the syntax-highlighting library (it's a Composer package; don't think about it too much!):\r\nrequire(__DIR__ . '\/..\/..\/vendor\/autoload.php');\r\n\r\n\/\/ Define a constant for the site title.\r\ndefine( 'SITE_TITLE', \"Dan Q's PHP Cookery Class\" );\r\n\r\n\/\/ Load the code used for the Potion Finder game referenced in Lesson 6:\r\nrequire('potion-finder.php');\r\n\r\n\/**\r\n * Renders the page header. Accepts the following parameters:\r\n * - $page_title: Optional, default null. The title of the page; used in the browser tab etc.\r\n * - $hide_navbar: Optional, default false. Whether to suppress the navigation bar.\r\n *\/\r\nfunction add_header( $page_title = null, $hide_navbar = false ) {\r\n \/\/ We start by setting the full page title to the site title.\r\n $full_page_title = SITE_TITLE;\r\n \/\/ If a page title is provided, we prepend it to the full page title.\r\n if( ! empty( $page_title ) ) {\r\n $full_page_title = $page_title . ' - ' . $full_page_title;\r\n }\r\n \/\/ Now we load the header template:\r\n require('header.php');\r\n}\r\n\r\n\/**\r\n * Renders the page footer.\r\n *\/\r\nfunction add_footer() {\r\n \/\/ Load the footer template:\r\n require('footer.php');\r\n}\r\n\r\n\/**\r\n * Renders the navigation bar.\r\n * It's generated from a list of links, and the one which is the current page is marked as \"active\"\r\n * (so that it can be styled differently).\r\n * Accepts the following parameters:\r\n * - $full_toc: Optional, default false. Set to true to render all sections in each link, even if that link's not open.\r\n *\/\r\nfunction add_navbar($full_toc = false) {\r\n \/\/ Set up an array of links:\r\n $links = [\r\n [\r\n 'title' => 'Home',\r\n 'href' => '\/',\r\n ],\r\n [\r\n 'title' => 'Introduction',\r\n 'href' => '\/01-intro\/',\r\n ],\r\n [\r\n 'title' => 'Hello World',\r\n 'href' => '\/02-hello-world\/',\r\n 'sections' => [\r\n [\r\n 'id' => 'strings-both-ways',\r\n 'title' => 'Strings, forwards and backwards'\r\n ],\r\n [\r\n 'id' => 'today',\r\n 'title' => 'What day is it?'\r\n ],\r\n [\r\n 'id' => 'conditional',\r\n 'title' => 'Closed on Mondays!'\r\n ],\r\n ],\r\n ],\r\n [\r\n 'title' => 'Lists and Loops',\r\n 'href' => '\/03-lists-and-loops\/',\r\n 'sections' => [\r\n [\r\n 'id' => 'looping',\r\n 'title' => 'The 7-times table'\r\n ],\r\n [\r\n 'id' => 'looping-through-a-list',\r\n 'title' => 'A basic gallery'\r\n ],\r\n [\r\n 'id' => 'navigation-menu',\r\n 'title' => 'Navigation menu'\r\n ],\r\n [\r\n 'id' => 'looping-through-files',\r\n 'title' => 'Looping through files (automatic gallery)'\r\n ],\r\n [\r\n 'id' => 'selecting-from-an-array',\r\n 'title' => 'Showing a random quote'\r\n ],\r\n ]\r\n ],\r\n [\r\n 'title' => 'Includes and Functions',\r\n 'href' => '\/04-includes-and-functions\/',\r\n 'sections' => [\r\n [\r\n 'id' => 'navigation-menu-include',\r\n 'title' => 'Sharing your navbar across the site'\r\n ],\r\n [\r\n 'id' => 'functions',\r\n 'title' => 'Reusing common patterns with functions'\r\n ],\r\n [\r\n 'id' => 'shared-function-file',\r\n 'title' => 'Sharing a function across multiple pages'\r\n ],\r\n ],\r\n ],\r\n [\r\n 'title' => 'Accepting Input',\r\n 'href' => '\/05-accepting-input\/',\r\n 'sections' => [\r\n [\r\n 'id' => 'get-and-post',\r\n 'title' => 'GET and POST requests'\r\n ],\r\n [\r\n 'id' => 'whats-your-name',\r\n 'title' => \"Asking the user's name\"\r\n ],\r\n [\r\n 'id' => 'fruits-and-filters',\r\n 'title' => 'Fruits and filters revisited'\r\n ],\r\n [\r\n 'id' => 'quiz',\r\n 'title' => \"Let's make a quiz!\"\r\n ],\r\n ],\r\n ],\r\n [\r\n 'title' => 'Sessions & Cookies',\r\n 'href' => '\/06-retaining-state\/',\r\n 'sections' => [\r\n [\r\n 'id' => 'what-are-cookies',\r\n 'title' => 'What are cookies?'\r\n ],\r\n [\r\n 'id' => 'detecting-repeat-visitors',\r\n 'title' => 'Detecting repeat visitors'\r\n ],\r\n [\r\n 'id' => 'sessions',\r\n 'title' => 'Logging in (and staying logged in)'\r\n ],\r\n [\r\n 'id' => 'potion-finder',\r\n 'title' => 'Potion Finder (game)'\r\n ],\r\n ],\r\n ],\r\n [\r\n 'title' => 'Storing Data',\r\n 'href' => '\/07-storing-data\/',\r\n \/\/ comments\/guestbook, text hit counter\r\n ],\r\n [\r\n 'title' => 'Beyond HTML',\r\n 'href' => '\/08-beyond-html\/',\r\n \/\/ Generating RSS, constructing a custom ZIP file, composing images, image hit counter?\r\n ],\r\n [\r\n 'title' => 'Reaching Out',\r\n 'href' => '\/09-reaching-out\/',\r\n \/\/ Sending mail, downloading RSS, getting data from APIs?\r\n ],\r\n [\r\n 'title' => 'Troubleshooting',\r\n 'href' => '\/troubleshooting\/',\r\n ],\r\n [\r\n 'title' => 'Full table of contents',\r\n 'href' => '\/toc\/',\r\n 'class' => [ 'no-number' ],\r\n ],\r\n [\r\n 'title' => 'Appendix A: Further Examples',\r\n 'href' => '\/appendix-samples\/',\r\n 'class' => [ 'no-number', 'appendix' ],\r\n ],\r\n [\r\n 'title' => 'Appendix B: Security',\r\n 'href' => '\/appendix-security\/',\r\n 'class' => [ 'no-number', 'appendix' ],\r\n ],\r\n [\r\n 'title' => \"Appendix C: This Site's Code\",\r\n 'href' => '\/appendix-quine\/',\r\n 'class' => [ 'no-number', 'appendix' ],\r\n ],\r\n ];\r\n ?>\r\n <nav>\r\n <ol start=\"0\">\r\n <?php\r\n \/\/ Loop through each link:\r\n foreach( $links as $link ) {\r\n \/\/ Decide if this link is the current page:\r\n $is_active = $_SERVER['REQUEST_URI'] === $link['href'];\r\n \/\/ Come up with a class list for the link:\r\n $class_list = $link['class'] ?? [];\r\n if( $is_active ) {\r\n $class_list[] = 'active';\r\n }\r\n \/\/ Join the class list together into a string:\r\n $class_list = implode( ' ', $class_list );\r\n \/\/ Render the link:\r\n ?>\r\n <li class=\"<?php echo $class_list; ?>\">\r\n <a href=\"<?php echo $link['href']; ?>\"><?php echo $link['title']; ?><\/a>\r\n <?php if( $full_toc || ( $is_active && ! empty( $link['sections'] ) ) ) { ?>\r\n <ul>\r\n <?php foreach( $link['sections'] as $section ) { ?>\r\n <li><a href=\"<?php echo $link['href'] . '#' . $section['id']; ?>\"><?php echo $section['title']; ?><\/a><\/li>\r\n <?php } ?>\r\n <\/ul>\r\n <?php } ?>\r\n <\/li>\r\n <?php\r\n }\r\n ?>\r\n <\/ol>\r\n <\/nav>\r\n <?php\r\n}\r\n\r\n\/* Adds a \"back\" link in a paragraph. The link only appears if JavaScript is enabled. *\/\r\nfunction add_backlink() {\r\n ?>\r\n <p class=\"back\"><\/p>\r\n <script>\r\n \/* Add a JavaScript-powered \"back\" link, using JavaScript so it doesn't appear if JavaScript is disabled. *\/\r\n const backLink = document.createElement('a');\r\n backLink.href = '#';\r\n backLink.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n window.history.back();\r\n });\r\n backLink.innerText = '\ud83d\udd19 Back to the site';\r\n document.querySelector('.back').appendChild(backLink);\r\n <\/script>\r\n <?php\r\n}\r\n\r\n\/**\r\n * Begins a syntax-highlighted code block.\r\n * Accepts the following parameters:\r\n * - $language: Optional, default null. The language of the code. If not provided, no language will be assumed.\r\n *\/\r\nfunction begin_code_block( $language = null ){\r\n global $current_code_block_language;\r\n $current_code_block_language = $language;\r\n ob_start();\r\n}\r\n\r\n\/**\r\n * Ends a syntax-highlighted code block and renders the output\r\n *\/\r\nfunction end_code_block(){\r\n global $current_code_block_language;\r\n $hl = new \\Highlight\\Highlighter();\r\n if( ! empty( $current_code_block_language ) ) {\r\n $hl->setAutodetectLanguages(array($current_code_block_language));\r\n } else {\r\n $hl->setAutodetectLanguages(array('php', 'html', 'css', 'javascript'));\r\n }\r\n $code = ob_get_clean();\r\n $highlighted = $hl->highlightAuto( htmlspecialchars_decode( $code ) );\r\n echo '<figure class=\"code-block-container\"><pre class=\"code-block\"><code class=\"hljs ' . $highlighted->language . '\">' . $highlighted->value . '<\/code><\/pre><\/figure>';\r\n}\r\n\r\n\/**\r\n * Renders a code block from a file.\r\n * Accepts the following parameters:\r\n * - $file: The relative path to the file to render.\r\n * - $language: Optional, default null. The language of the code. If not provided, no language will be assumed.\r\n * - $link: Optional, default true. Should there be a link to the URL of the file (to demo it).\r\n * - $download: Optional, default true. Whether to provide a link to download the file.\r\n * - $demo_in_full_page: Optional, default false. Set to true to wrap the code in a full HTML page when trying\/demoing it.\r\n * Set to a string to specify a CSS file to <link>\r\n *\/\r\nfunction code_block_from_file( $file, $language = null, $link = true, $download = true, $demo_in_full_page = false ) {\r\n $code = file_get_contents( __DIR__ . '\/..\/' . $file );\r\n $hl = new \\Highlight\\Highlighter();\r\n if( ! empty( $language ) ) {\r\n $highlighted = $hl->highlight($language, $code);\r\n } else {\r\n $hl->setAutodetectLanguages(array('php', 'html', 'css', 'javascript'));\r\n $highlighted = $hl->highlightAuto( htmlspecialchars_decode( $code ) );\r\n }\r\n $highlighted = $hl->highlightAuto( htmlspecialchars_decode( $code ) );\r\n $try_link = $demo_in_full_page ?\r\n '\/demo-harness.php?file=public\/' . $file . '&demo_in_full_page=' . $demo_in_full_page : \/\/ \ud83d\udc48 demo link URL if Demo In Full Page is set\r\n '\/' . $file; \/\/ \ud83d\udc48 raw demo link URL\r\n echo '<figure class=\"code-block-container\"><pre class=\"code-block\"><code class=\"hljs ' . $highlighted->language . '\">' . $highlighted->value . '<\/code><\/pre>';\r\n if( $link || $download ) {\r\n echo '<figcaption class=\"code-block-actions\"><ul>';\r\n if( $link ) {\r\n echo '<li><a href=\"' . $try_link . '\">\ud83d\udc41\ufe0f Try it!<\/a><\/li>';\r\n }\r\n if( $download ) {\r\n echo '<li><a href=\"\/source-viewer.php?file=public\/' . $file . '&download=true\" download>\ud83d\udcbe Download<\/a><\/li>';\r\n }\r\n echo '<\/ul><\/figcaption>';\r\n }\r\n echo '<\/figure>';\r\n}\r\n\r\n\/**\r\n * Given a relative or absolute file path, returns a sanitized absolute version of the path.\r\n * Forbids access to files outside of this application's directory structure.\r\n *\/\r\nfunction sanitize_file_path( $file_path ) {\r\n \/\/ The allowed directory (from which files can be requested) is the parent directory of this file.\r\n $allowed_directory = realpath( __DIR__ . '\/..\/..\/' );\r\n \r\n \/\/ If they didn't specify a file, give them a 404 error:\r\n if( empty( $file_path ) ) {\r\n header('HTTP\/1.1 404 Missing file parameter');\r\n die('Missing file parameter');\r\n }\r\n \r\n \/\/ Move to the allowed directory so that we treat paths as \"relative\" to that:\r\n chdir( $allowed_directory );\r\n \r\n \/\/ Determine the real path of the file they're requesting:\r\n $real_file_path = realpath( $file_path );\r\n\r\n \/\/ If the file doesn't exist, give them a 404 error:\r\n if( $real_file_path === false ) {\r\n header('HTTP\/1.1 404 Requested file not found');\r\n die('Requested file not found');\r\n }\r\n\r\n \/\/ Ensure that the file they're requesting is within the allowed directory so they can't read ANY file on this server!\r\n \/\/ If the file they want is not in the allowed directory, give them a 403 error:\r\n if( strpos( $real_file_path, $allowed_directory ) !== 0 ) {\r\n header('HTTP\/1.1 403 Requested file forbidden');\r\n die('Requested file forbidden');\r\n }\r\n\r\n return $real_file_path;\r\n}\r\n\r\n\/**\r\n * Some pages (the source viewer and demo harness) will show the source code of or render a specified file.\r\n * This convenience function works out what file they've requested (from the $_GET['file'] parameter),\r\n * checks that it's a legitimate request (a real file, found within this application's directory structure),\r\n * kills the request if it's not, and returns the real path to the file if it is.\r\n *\/\r\nfunction get_requested_file() {\r\n\/\/ Find out what file the user wants to view the source code for:\r\n return sanitize_file_path( $_GET['file'] );\r\n}\r\n\r\n\/**\r\n * Given a PHP file path, returns the path to the associated CSS file if it exists.\r\n *\/\r\nfunction get_associated_css_file( $file ) {\r\n $file = sanitize_file_path( $file );\r\n $css_file_path = str_replace('.php', '.css', $file );\r\n if( file_exists( $css_file_path ) ) {\r\n $public_dir = realpath( __DIR__ . '\/..\/' );\r\n return str_replace( $public_dir, '', $css_file_path );\r\n }\r\n return null;\r\n}"
},
{
"url": "\/header.php",
"kind": "code",
"title": "header.php",
"body": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <link rel=\"stylesheet\" href=\"\/css\/style.css\">\r\n <link rel=\"icon\" type=\"image\/png\" href=\"\/favicon-96x96.png\" sizes=\"96x96\" \/>\r\n <link rel=\"icon\" type=\"image\/svg+xml\" href=\"\/favicon.svg\" \/>\r\n <link rel=\"shortcut icon\" href=\"\/favicon.ico\" \/>\r\n <link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"\/apple-touch-icon.png\" \/>\r\n <meta name=\"apple-mobile-web-app-title\" content=\"PHP Cookery Class\" \/>\r\n <link rel=\"manifest\" href=\"\/manifest.json\" \/>\r\n <style>\r\n <?php\r\n \/\/ Inject the source code highlighting stylesheet:\r\n echo \\HighlightUtilities\\getStyleSheet('atom-one-dark');\r\n ?>\r\n <\/style>\r\n <title><?php echo strip_tags($full_page_title); ?><\/title>\r\n <meta property=\"og:title\" content=\"Dan Q's PHP Cookery Class\" \/>\r\n <meta property=\"og:type\" content=\"website\" \/>\r\n <meta property=\"og:url\" content=\"https:\/\/php.danq.dev\/\" \/>\r\n <meta property=\"og:image\" content=\"https:\/\/php.danq.dev\/og.png\" \/>\r\n <meta property=\"og:description\" content=\"Introductory lessons in PHP geared towards Web Revivalists.\" \/>\r\n<\/head>\r\n<body>\r\n <div class=\"page\">\r\n <header>\r\n <a href=\"\/\">\r\n <?php\r\n \/* The SITE_TITLE is a constant defined in functions.php\r\n * If we DON'T have an individual page title, we'll wrap it in a <h1> so that screen readers know that the site title IS the page title,\r\n * otherwise we'll just display it in a <p> tag.\r\n * Our CSS will make these both look the same anyway, but using the right one helps screen readers!\r\n *\/\r\n if( empty( $page_title ) ) {\r\n echo '<h1 class=\"title\">' . SITE_TITLE . '<\/h1>';\r\n } else {\r\n echo '<p class=\"title\">' . SITE_TITLE . '<\/p>';\r\n }\r\n ?>\r\n <p class=\"subtitle\">\r\n An intro to PHP for Web Revivalists\r\n <\/p>\r\n <\/a>\r\n <\/header>\r\n\r\n <?php\r\n if( ! $hide_navbar ) {\r\n add_navbar(); \/* Adds the <nav> section here! *\/\r\n }\r\n ?>\r\n\r\n <main>\r\n <?php\r\n \/\/ If we have a page title, display it as a heading here:\r\n if( ! empty( $page_title ) ) {\r\n echo '<h1>' . $page_title . '<\/h1>';\r\n }\r\n ?>\r\n\r\n <?php \/* Note that we don't need to end the <\/body> or <\/html> tags here - that's done in the footer.php file. *\/ ?>"
},
{
"url": "\/potion-finder.php",
"kind": "code",
"title": "potion-finder.php",
"body": "<?php\r\n\/**\r\n * Potion Finder!\r\n *\r\n * A \"find it\" game spread throughout Dan Q's PHP Cookery Class.\r\n * Four potions (blue, green, red, and yellow) are hidden on different pages of the site.\r\n * The player must find them all by clicking on them.\r\n *\/\r\n\r\n\/\/ Start the session and set up an array to keep the \"found\" potions\r\nsession_start();\r\n\r\n\/\/ $_SESSION['found_potions'] will be an array of the colors of the potions that have been found.\r\n\/\/ We'll load it into a variable (or an empty array if no potions have been found yet).\r\n$found_potions = isset( $_SESSION['found_potions'] ) ? $_SESSION['found_potions'] : [];\r\n\r\n\/\/ Keep a list of potions and their passwords (the passwords ensure that visitors have to find\r\n\/\/ the links, which contain the passwords: they can't just go to e.g. ?potion=blue!)\r\n$potion_passwords = [\r\n 'blue' => 'JNEvDcic',\r\n 'green' => '9PoqhPpV',\r\n 'red' => 'bzfUfuQV',\r\n 'yellow' => 'zbPADf4r',\r\n];\r\n\r\n \/**\r\n * Creates a potion link on the current page. Takes the following parameters:\r\n * - $color: The color of the potion.\r\n * The link is only shown if the user HASN'T already found the potion.\r\n *\/\r\nfunction draw_potion( $color ){\r\n \/\/ Get access to the $found_potions variable:\r\n global $found_potions, $potion_passwords;\r\n\r\n \/\/ Check if the potion has already been found:\r\n if( in_array( $color, $found_potions ) ){\r\n return; \/\/ This potion has already been found - return without drawing anything!\r\n }\r\n\r\n \/\/ Determine the password to acttach to this potion (this stops users just going to e.g.\r\n \/\/ ?potion=blue to claim a potion; they need the password which only appears with the link,\r\n \/\/ although of course YOU know the passwords because you're reading the source code!)\r\n $password = $potion_passwords[ $color ];\r\n\r\n \/\/ Draw the potion:\r\n ?>\r\n <p class=\"potion\">\r\n <a href=\"\/?potion=<?php echo $color; ?>&potion_password=<?php echo $password; ?>\"><img class=\"potion-img\" src=\"\/img\/potions\/<?php echo $color; ?>.png\" alt=\"<?php echo ucfirst($color); ?> potion\"><\/a>\r\n <span>\r\n You found the <?php echo $color ?> potion! Click on it to collect it!\r\n (<a href=\"\/?show_potions=true\">What is this?<\/a>)\r\n <\/span>\r\n <\/p>\r\n <?php\r\n}\r\n\r\n\/\/ Captue requests to reset the game (discard all potions):\r\nif( isset( $_GET['reset_potions'] ) && $_GET['reset_potions'] === 'true' ){\r\n \/\/ Reset the game:\r\n $found_potions = [];\r\n $_SESSION['found_potions'] = $found_potions;\r\n \/\/ Redirect the user to the potions collection page:\r\n header( 'Location: \/?show_potions=true' );\r\n die();\r\n}\r\n\r\n\/\/ Capture requests to collect potions:\r\nif( isset( $_GET['potion'] ) && isset( $_GET['potion_password'] ) ){\r\n \/\/ Check if the password is correct:\r\n if( $_GET['potion_password'] !== $potion_passwords[ $_GET['potion'] ] ){\r\n \/\/ It's not correct! Show a HTTP 403 error and stop:\r\n header( 'HTTP\/1.1 403 Forbidden' );\r\n die( 'Invalid potion. The potion you tried to collect was not authorised.' );\r\n }\r\n\r\n \/\/ Add the potion to the user's collection, unless it's already been found:\r\n if( ! in_array( $_GET['potion'], $found_potions ) ){\r\n $found_potions[] = $_GET['potion'];\r\n }\r\n\r\n \/\/ Save the updated collection back to the session:\r\n $_SESSION['found_potions'] = $found_potions;\r\n\r\n \/\/ Redirect the user to the potions collection page:\r\n header( 'Location: \/?show_potions=true' );\r\n die();\r\n}\r\n\r\n\/\/ Capture requests to show the potions collection:\r\nif( isset( $_GET['show_potions'] ) && $_GET['show_potions'] === 'true' ){\r\n \/\/ Show the potions collection:\r\n add_header( 'Potions Collection' );\r\n ?>\r\n <h2>Your Potions<\/h2>\r\n <p>\r\n <a href=\"\/06-retaining-state\/\">Lesson 6<\/a> of Dan Q's PHP Cookery Class is all about <em>sessions<\/em> and <em>cookies<\/em>.\r\n One of the demonstrations it gives is a game where you must explore the site and find hidden potions.\r\n <\/p>\r\n <p>\r\n You have found <?php echo count( $found_potions ); ?> potions!\r\n <\/p>\r\n <?php if( count( $found_potions ) > 0 ){ ?>\r\n <p>You have found:<\/p>\r\n <ul class=\"potion-list\">\r\n <?php foreach( $found_potions as $potion ){ ?>\r\n <li>\r\n <img class=\"potion-img\" src=\"\/img\/potions\/<?php echo $potion; ?>.png\" alt=\"\">\r\n <span>The <?php echo $potion; ?> potion<\/span>\r\n <\/li>\r\n <?php } ?>\r\n <\/ul>\r\n <?php if( count( $found_potions ) === count( $potion_passwords ) ){ ?>\r\n <p>\r\n That's all four potions! Congratulations!\r\n <\/p>\r\n <p>\r\n If you want to play again, you'll need to\r\n <a href=\"\/?reset_potions=true\">discard all of your potions<\/a>.\r\n <\/p>\r\n <?php } ?>\r\n <?php } ?>\r\n\r\n <h2>Where to find potions?<\/h2>\r\n <p>\r\n The potions are hidden on different pages of the site. Here are some clues about where you might find them:\r\n <\/p>\r\n <ul>\r\n <li <?php echo in_array( 'blue', $found_potions ) ? 'style=\"text-decoration: line-through;\"' : ''; ?>>\r\n <img src=\"\/img\/potions\/blue.png\" alt=\"\">\r\n The blue potion is found <a href=\"\/06-retaining-state\/#potion-finder\">where the Potion Finder game was invented<\/a>.\r\n <\/li>\r\n <li <?php echo in_array( 'green', $found_potions ) ? 'style=\"text-decoration: line-through;\"' : ''; ?>>\r\n <img src=\"\/img\/potions\/green.png\" alt=\"\">\r\n The green potion is found amongst some tips on security.\r\n <\/li>\r\n <li <?php echo in_array( 'red', $found_potions ) ? 'style=\"text-decoration: line-through;\"' : ''; ?>>\r\n <img src=\"\/img\/potions\/red.png\" alt=\"\">\r\n The red potion can be found in the navigation menu. No... not the one on the side of the page... the <em>other<\/em> one!\r\n <\/li>\r\n <li <?php echo in_array( 'yellow', $found_potions ) ? 'style=\"text-decoration: line-through;\"' : ''; ?>>\r\n <img src=\"\/img\/potions\/yellow.png\" alt=\"\">\r\n The yellow potion can only be found... if you get completely lost!\r\n <\/li>\r\n <\/ul>\r\n\r\n <h2>Or if you'd rather cheat...<\/h2>\r\n <p>\r\n <a href=\"\/source-viewer.php?file=public\/inc\/potion-finder.php\">View the source code of this game<\/a>\r\n <\/p>\r\n\r\n <?php\r\n add_footer();\r\n\r\n die(); \/\/ Don't go on to render the normal page content!\r\n}"
}
]