* Copyright 2001-2012 Strangecode, LLC * * This file is part of The Strangecode Codebase. * * The Strangecode Codebase is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) * any later version. * * The Strangecode Codebase is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * The Strangecode Codebase. If not, see . */ /** * Navigation.inc.php * * The Nav class provides a system for working with navigation elements. * It supports storing page titles and URLs for printing breadcrumbs * and titles, as well as setting page params such as hiding the page title on * some pages but not others, and storing vars like the page title itself. * * Note: this class was renamed from "Nav" because of the change in API and to be more descriptive. * * @author Quinn Comendant * @version 2.0 */ class Navigation { // Configuration parameters for this object. protected $_params = array( 'head_title' => true, 'body_title' => true, 'title' => true, 'path' => true, 'breadcrumbs' => true, 'chop_breadcrumbs' => 0, 'chop_breadcrumb_links' => 1, 'path_delimiter' => ' / ', 'last_crumb_format' => '%s', 'current_page_url' => null, // This should be set at runtime using, e.g., $_SERVER['REQUEST_URI'] ); public $pages = array(); /** * Navigation constructor. */ public function __construct(Array $params=[]) { $app =& App::getInstance(); // Define current_page_url here because _SERVER, not a static scalar, cannot be defined in the defaults above. // Using PHP_SELF for legacy compatibility, but it might make sense to override this with REQUEST_URI. // This could be overwritten by passed params. $this->_params['current_page_url'] = $_SERVER['PHP_SELF']; if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } } /** * Add a page to the internal pages array. Pages must be added sequentially * as they are to be printed. The root page must be added first, and the * current page added last. Vars can be specified for any page, but only vars * from the "current" page will be accessed with Nav::get. * * @access public * @param string $title The title of the page. * @param string $url The URL to the page. Set to null to use REQUEST_URI. * @param array $vars Additional page variables. */ public function add($title, $url=null, $vars=array()) { $page = array( 'title' => $title, 'head_title' => $title, 'body_title' => $title, 'url' => is_null($url) ? $this->_params['current_page_url'] : $url, ); // An "unformed page element" has settings applied (via ->set()) but no page added (via ->add()). if (empty($this->pages) || isset(end($this->pages)['title'])) { // There are no unformed page elements; add a whole new page. $this->pages[] = array_merge($page, $vars); } else { // Append the new page to the unformed page element. $curr_page =& $this->pages[key($this->pages)]; $curr_page = array_merge($curr_page, $page, $vars); } } /** * Set (or overwrite existing) parameters by passing an array of new parameters. * * @access public * @param array $params Array of parameters (key => val pairs). */ public function setParam($params) { $app =& App::getInstance(); if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } else { $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__); } } /** * Return the value of a parameter, if it exists. * * @access public * @param string $param Which parameter to return. * @return mixed Configured parameter value. */ public function getParam($param) { $app =& App::getInstance(); if (array_key_exists($param, $this->_params)) { return $this->_params[$param]; } else { $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__); return null; } } /** * Unsets all pages. * * @access public */ public function clear() { $this->pages = array(); } /** * Sets a variable into the current page. * * @access public * @param mixed $key Which value to set. * @param mixed $val Value to set variable to. */ public function set($key, $val) { // Set params of current page. if (empty($this->pages)) { // If we're setting a value on an empty pages array, we need to add one "unformed" element first. $this->pages[] = array(); } end($this->pages); $curr_page =& $this->pages[key($this->pages)]; $curr_page[$key] = $val; } /** * Returns a specified value from the current page. * * @access public * @param mixed $key Which value to return. * @param mixed $default Value to return if key not found in user_data. * @return mixed Value stored in session. */ public function get($key, $default='') { end($this->pages); $curr_page =& $this->pages[key($this->pages)]; switch ($key) { case 'title' : if ($this->getParam('title') && isset($curr_page['title'])) { return $curr_page['title']; } break; case 'head_title' : if ($this->getParam('head_title') && $this->getParam('title') && isset($curr_page['head_title'])) { return $curr_page['head_title']; } break; case 'body_title' : if ($this->getParam('body_title') && $this->getParam('title') && isset($curr_page['body_title'])) { return $curr_page['body_title']; } break; case 'path' : if ($this->getParam('path')) { return $this->getPath(); } break; case 'breadcrumbs' : if ($this->getParam('breadcrumbs')) { return $this->getBreadcrumbs(); } break; default : return isset($curr_page[$key]) ? $curr_page[$key] : $default; break; } return $default; } /** * Returns the path from root up to the current page as an array. * * @access public * @param string $key Which value to use in the path (usually head_title or body_title or just title). * @return mixed Path (string) or false if path param is not set. */ public function getPathArray($key='title') { $path = array(); if ($this->getParam('path')) { foreach ($this->pages as $page) { $path[] = strip_tags($page[$key]); } } return $path; } /** * Returns the text path from root up to the current page, separated by the * path_delimiter. * * @access public * @param string $key Which value to use in the path (usually head_title or body_title or just title). * @return mixed Path (string) or false if path param is not set. */ public function getPath($key='title') { $path = $this->getPathArray($key); return empty($path) ? '' : join(oTxt($this->getParam('path_delimiter'), true), $path); } /** * Returns the breadcrumbs from the root page to the current page. * Breadcrumbs are the text path with pages titles linked to that page. * * @access public * @return string Breadcrumbs or empty string if breadcrumbs param not set. */ public function getBreadcrumbsArray($carry_args=null) { $app =& App::getInstance(); if ($this->getParam('breadcrumbs')) { $breadcrumbs = array(); $crumb_count = sizeof($this->pages); foreach ($this->pages as $page) { if ($crumb_count <= $this->getParam('chop_breadcrumbs')) { // Stop gathering crumbs. break; } if (!is_null($carry_args)) { // If this function is called with $carry_args, employ the ohref() method. $url = $app->ohref($page['url'], $carry_args); } else { // Otherwise let the URL pass through as-is (the wise developer must have provided the correct URL when calling $nav->add(…)). $url = $page['url']; } if ($crumb_count <= 1) { // The last crumb. if ('' == trim($page['url']) || $crumb_count <= $this->getParam('chop_breadcrumb_links')) { // A last crumb with no link. $breadcrumbs[] = array( 'url' => false, 'title' => sprintf($this->getParam('last_crumb_format'), $page['title']), 'class' => 'current' ); } else if ($crumb_count > $this->getParam('chop_breadcrumb_links')) { // A last linked crumb. $breadcrumbs[] = array( 'url' => $url, 'title' => sprintf($this->getParam('last_crumb_format'), $page['title']), 'class' => '', ); } } else { if ('' == trim($page['url'])) { // A crumb with no link. $breadcrumbs[] = array( 'url' => false, 'title' => $page['title'], 'class' => 'unavailable', ); } else { // A normal linked crumb. $breadcrumbs[] = array( 'url' => $url, 'title' => $page['title'], 'class' => '', ); } } $crumb_count--; } return $breadcrumbs; } else { return array(); } } /** * Returns the breadcrumbs from the root page to the current page. * Breadcrumbs are the text path with pages titles linked to that page. * * @access public * @return string Breadcrumbs or empty string if breadcrumbs param not set. */ public function getBreadcrumbs($carry_args=null) { $app =& App::getInstance(); if ($this->getParam('breadcrumbs')) { $breadcrumbs = array(); $pathmark = ''; $crumb_count = sizeof($this->pages); foreach ($this->pages as $page) { if ($crumb_count <= $this->getParam('chop_breadcrumbs')) { // Stop gathering crumbs. break; } if (!is_null($carry_args)) { // If this function is called with $carry_args, employ the ohref() method. $url = $app->ohref($page['url'], $carry_args); } else { // Otherwise let the URL pass through as-is (the wise developer must have provided the correct URL when calling $nav->add(…)). $url = $page['url']; } if ($crumb_count <= 1) { // The last crumb. if ('' == trim($page['url']) || $crumb_count <= $this->getParam('chop_breadcrumb_links')) { // A last crumb with no link. $breadcrumbs[] = sprintf($this->getParam('last_crumb_format'), oTxt($page['title'], true)); } else if ($crumb_count > $this->getParam('chop_breadcrumb_links')) { // A last linked crumb. $breadcrumbs[] = '' . sprintf($this->getParam('last_crumb_format'), oTxt($page['title'], true)) . ''; } } else { if ('' == trim($page['url'])) { // A crumb with no link. $breadcrumbs[] = oTxt($pathmark . $page['title'], true); } else { // A normal linked crumb. $breadcrumbs[] = '' . oTxt($page['title'], true) . ''; } } $pathmark = $this->getParam('path_delimiter'); $crumb_count--; } return join(oTxt($pathmark, true), $breadcrumbs); } else { return ''; } } /* * * * @access public * @param * @return * @author Quinn Comendant * @version 1.0 * @since 07 Sep 2014 12:22:19 */ public function getBreadcrumbsUL($carry_args=null, $ul_open_tag=''; } return $out; } /** * Test if the given URI matches the URL of the current page. By default the URI is tested * without concern * One use is to change the returned value for a positive match * so a css class prints for an element representing the current page: * echo $nav->currentPage('/script.php?op=info', ' class="current"', '', true); * The above will match only if the current page (REQUEST_URI) is also '/script.php?op=info', * and will return the string ' class="current"' if it is. * * @access public * * @param mixed $test_uri A URI, or an array of URIs, to test against the current page. * @param mixed $true_return The value to return if the current page matches the test URI. * @param mixed $false_return The value to return if the current page does not match the test URI. * @param bool $include_query If set true, include the URI query string in the test. * * @return mixed If the test URI matches the current page URI, the value given for $true_return * is returned (true by default), otherwise the value given for $false_return is * returned (false by default). */ public function currentPage($test_uri, $true_return=true, $false_return=false, $include_query=false) { $app =& App::getInstance(); // If given an array, test each URI recursively returning TRUE on a first match, or FALSE if none match. if (is_array($test_uri)) { foreach ($test_uri as $uri) { if ($this->currentPage($uri, $true_return, $false_return, $include_query)) { return true; } } return false; } $actual_uri = $include_query ? $_SERVER['REQUEST_URI'] : (strstr(getenv('REQUEST_URI'), '?', true) ?: getenv('REQUEST_URI')); // strstr() returns false if '?' is not found, so use a shorthand ternary operator. $test_uri = $include_query ? $test_uri : (strstr($test_uri, '?', true) ?: $test_uri); // strstr() returns false if '?' is not found, so use a shorthand ternary operator. if (mb_strtolower($test_uri) == mb_strtolower($actual_uri)) { // $app->logMsg(sprintf('Current page (%s) == test URI (%s)', $actual_uri, $test_uri), LOG_DEBUG, __FILE__, __LINE__); return $true_return; } // $app->logMsg(sprintf('Current page (%s) != test URI (%s)', $actual_uri, $test_uri), LOG_DEBUG, __FILE__, __LINE__); return $false_return; } } // End of class.