diff --git a/src/classes/API/AYAH.php b/src/classes/API/AYAH.php index f32fe87..9822705 100644 --- a/src/classes/API/AYAH.php +++ b/src/classes/API/AYAH.php @@ -22,33 +22,32 @@ */ class API_AYAH { - public static function getHTML() - { - $config = Config::getInstance(); + public static function getHTML() + { + $config = Config::getInstance(); - if (!$config->api['ayah']) - { - throw new Exception('Missing API configuration.'); - } + if (!$config->api['ayah']) + { + throw new Exception('Missing API configuration.'); + } - $ayah = new AYAH($config->api['ayah']); + $ayah = new AYAH($config->api['ayah']); - return $ayah->getPublisherHTML(); - } + return $ayah->getPublisherHTML(); + } - public static function isHuman() - { - $config = Config::getInstance(); + public static function isHuman() + { + $config = Config::getInstance(); - if (!$config->api['ayah']) - { - throw new Exception('Missing API configuration.'); - } + if (!$config->api['ayah']) + { + throw new Exception('Missing API configuration.'); + } - $ayah = new AYAH($config->api['ayah']); + $ayah = new AYAH($config->api['ayah']); - return $ayah->scoreResult(); - } + return $ayah->scoreResult(); + } } -?> diff --git a/src/classes/API/Google/Profanity.php b/src/classes/API/Google/Profanity.php index fd1e0fc..1126168 100644 --- a/src/classes/API/Google/Profanity.php +++ b/src/classes/API/Google/Profanity.php @@ -20,30 +20,29 @@ */ class API_Google_Profanity { - /** - * Check - * - * Checks if a word is considered profanity. - * - * @usage API_Google_Profanity::check('fuck'); // returns true - * @param string $word word to check - * @param string $endpoint the endpoint to call (helps testing) - * @return boolean whether or not the word is profanity - */ - public static function check($word, $endpoint = 'http://www.wdyl.com/profanity?q=') - { - $response = json_decode(file_get_contents($endpoint . $word), true); + /** + * Check + * + * Checks if a word is considered profanity. + * + * @usage API_Google_Profanity::check('fuck'); // returns true + * @param string $word word to check + * @param string $endpoint the endpoint to call (helps testing) + * @return boolean whether or not the word is profanity + */ + public static function check($word, $endpoint = 'http://www.wdyl.com/profanity?q=') + { + $response = json_decode(file_get_contents($endpoint . $word), true); - if ($response == null || !isset($response['response']) - || !in_array($response['response'], ['true', 'false'])) - { - throw new Exception('Invalid response from API.'); - } - else - { - return $response['response'] == 'true'; - } - } + if ($response == null || !isset($response['response']) + || !in_array($response['response'], ['true', 'false'])) + { + throw new Exception('Invalid response from API.'); + } + else + { + return $response['response'] == 'true'; + } + } } -?> diff --git a/src/classes/API/Gravatar.php b/src/classes/API/Gravatar.php index 770a7a4..6243fce 100644 --- a/src/classes/API/Gravatar.php +++ b/src/classes/API/Gravatar.php @@ -22,78 +22,77 @@ */ class API_Gravatar { - /** - * Hash - * - * Generates a hash from the passed string that can then be used for - * fetching an image or profile from Gravatar.com - * - * @static - * @param string $string string to hash, should be an email address - * @return string resulting hash - */ - public static function hash($string) - { - // Trims whitespace, lowers the case then applies MD5 - return md5(strtolower(trim($string))); - } + /** + * Hash + * + * Generates a hash from the passed string that can then be used for + * fetching an image or profile from Gravatar.com + * + * @static + * @param string $string string to hash, should be an email address + * @return string resulting hash + */ + public static function hash($string) + { + // Trims whitespace, lowers the case then applies MD5 + return md5(strtolower(trim($string))); + } - /** - * img - * - * Generates an img tag requesting a Gravatar based on the parameters. - * - * @static - * @param string $email address to use for the hash - * @param integer $size optional size of the image requested - * @param string $default optional default style or image to generate - * @param string $rating optional filter by a certain rating - * @param boolean $force optional force the default avatar - * @param boolean $secure optional whether to use the SSL URL - * @param array $attributes optional any additional parameters to include - * @return string an img tag requesting a Gravatar - */ - public static function img($email, $size = 80, $default = 'gravatar', $rating = 'g', $force = false, $secure = false, $attributes = false) - { - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) - { - throw new Exception('Invalid email address.'); - } - elseif ($size < 1 || $size > 2048) - { - throw new Exception('Invalid size parameter, expecting an integer between 1 and 2048.'); - } - elseif (!in_array($default, ['gravatar', '404', 'mm', 'identicon', 'monsterid', 'wavatar', 'retro', 'blank']) - && !filter_var($default, FILTER_VALIDATE_URL)) - { - throw new Exception('Invalid default parameter, expecting gravatar, 404, mm, identicon, monsterid, wavatar, retro, blank or a valid URL.'); - } - elseif (!in_array($rating, ['g', 'pg', 'r', 'x'])) - { - throw new Exception('Invalid rating parameter, expecting g, pg, r or x.'); - } - else - { - $default = $default == 'gravatar' ? false : urlencode($default); + /** + * img + * + * Generates an img tag requesting a Gravatar based on the parameters. + * + * @static + * @param string $email address to use for the hash + * @param integer $size optional size of the image requested + * @param string $default optional default style or image to generate + * @param string $rating optional filter by a certain rating + * @param boolean $force optional force the default avatar + * @param boolean $secure optional whether to use the SSL URL + * @param array $attributes optional any additional parameters to include + * @return string an img tag requesting a Gravatar + */ + public static function img($email, $size = 80, $default = 'gravatar', $rating = 'g', $force = false, $secure = false, $attributes = false) + { + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) + { + throw new Exception('Invalid email address.'); + } + elseif ($size < 1 || $size > 2048) + { + throw new Exception('Invalid size parameter, expecting an integer between 1 and 2048.'); + } + elseif (!in_array($default, ['gravatar', '404', 'mm', 'identicon', 'monsterid', 'wavatar', 'retro', 'blank']) + && !filter_var($default, FILTER_VALIDATE_URL)) + { + throw new Exception('Invalid default parameter, expecting gravatar, 404, mm, identicon, monsterid, wavatar, retro, blank or a valid URL.'); + } + elseif (!in_array($rating, ['g', 'pg', 'r', 'x'])) + { + throw new Exception('Invalid rating parameter, expecting g, pg, r or x.'); + } + else + { + $default = $default == 'gravatar' ? false : urlencode($default); - $html = ' $value) - { - $html .= sprintf(' %s="%s"', $attribute, $value); - } - } + if (is_array($attributes)) + { + foreach ($attributes as $attribute => $value) + { + $html .= sprintf(' %s="%s"', $attribute, $value); + } + } - $html .= '>'; + $html .= '>'; - return $html; - } - } + return $html; + } + } } -?> diff --git a/src/classes/API/PlaceholdIt.php b/src/classes/API/PlaceholdIt.php index 5b7bd08..6acc079 100644 --- a/src/classes/API/PlaceholdIt.php +++ b/src/classes/API/PlaceholdIt.php @@ -22,86 +22,85 @@ */ class API_PlaceholdIt extends Object { - /** - * URL - * - * Generates a Placehold.it URL based on the passed parameters. - * - * @param integer $width width of the image - * @param integer $height optional height of the image - * @param string $format optional format of the image - * @param string $background optional background color of the image - * @param string $foreground optional foreground color of the image - * @param string $text optional text to display in the image - * @return string Placehold.it URL - */ - public function url($width, $height = null, $format = 'gif', $background = null, $foreground = null, $text = null) - { - // Checks if the format is valid - if (!in_array($format, ['gif', 'jpeg', 'jpg', 'png'])) - { - throw new Exception('Invalid format. Valid formats: gif, jpeg, jpg and png.'); - } - // Checks if foreground is present without background - elseif ($foreground && !$background) - { - throw new Exception('You must specify a background color if you wish to specify a foreground color.'); - } - // Checks the background color's length - elseif ($background && strlen($background) < 6) - { - throw new Exception('The background color must be a 6 character hex code.'); - } - // Checks the foreground color's length - elseif ($foreground && strlen($foreground) < 6) - { - throw new Exception('The foreground color must be a 6 character hex code.'); - } + /** + * URL + * + * Generates a Placehold.it URL based on the passed parameters. + * + * @param integer $width width of the image + * @param integer $height optional height of the image + * @param string $format optional format of the image + * @param string $background optional background color of the image + * @param string $foreground optional foreground color of the image + * @param string $text optional text to display in the image + * @return string Placehold.it URL + */ + public function url($width, $height = null, $format = 'gif', $background = null, $foreground = null, $text = null) + { + // Checks if the format is valid + if (!in_array($format, ['gif', 'jpeg', 'jpg', 'png'])) + { + throw new Exception('Invalid format. Valid formats: gif, jpeg, jpg and png.'); + } + // Checks if foreground is present without background + elseif ($foreground && !$background) + { + throw new Exception('You must specify a background color if you wish to specify a foreground color.'); + } + // Checks the background color's length + elseif ($background && strlen($background) < 6) + { + throw new Exception('The background color must be a 6 character hex code.'); + } + // Checks the foreground color's length + elseif ($foreground && strlen($foreground) < 6) + { + throw new Exception('The foreground color must be a 6 character hex code.'); + } - $url = 'http://placehold.it/' . $width; + $url = 'http://placehold.it/' . $width; - if ($height) - { - $url .= 'x' . $height; - } + if ($height) + { + $url .= 'x' . $height; + } - $url .= '.' . $format; + $url .= '.' . $format; - if ($background) - { - $url .= '/' . $background; - } + if ($background) + { + $url .= '/' . $background; + } - if ($foreground) - { - $url .= '/' . $foreground; - } + if ($foreground) + { + $url .= '/' . $foreground; + } - if ($text) - { - $url .= '&text=' . urlencode($text); - } + if ($text) + { + $url .= '&text=' . urlencode($text); + } - return $url; - } + return $url; + } - /** - * URL - * - * Generates a Placehold.it tag based on the passed parameters. - * - * @param integer $width width of the image - * @param integer $height optional height of the image - * @param string $format optional format of the image - * @param string $background optional background color of the image - * @param string $foreground optional foreground color of the image - * @param string $text optional text to display in the image - * @return string tag with the Placehold.it URL - */ - public function img($width, $height = null, $format = 'gif', $background = null, $foreground = null, $text = null) - { - return ''; - } + /** + * URL + * + * Generates a Placehold.it tag based on the passed parameters. + * + * @param integer $width width of the image + * @param integer $height optional height of the image + * @param string $format optional format of the image + * @param string $background optional background color of the image + * @param string $foreground optional foreground color of the image + * @param string $text optional text to display in the image + * @return string tag with the Placehold.it URL + */ + public function img($width, $height = null, $format = 'gif', $background = null, $foreground = null, $text = null) + { + return ''; + } } -?> diff --git a/src/classes/Browser.php b/src/classes/Browser.php index dd5b9a7..41e4faa 100644 --- a/src/classes/Browser.php +++ b/src/classes/Browser.php @@ -23,266 +23,265 @@ */ class Browser extends Object { - /** - * Attributes - * - * Variables passed on the query string as /var:value/ - * - * @access private - * @var array - */ - private $attributes = []; + /** + * Attributes + * + * Variables passed on the query string as /var:value/ + * + * @access private + * @var array + */ + private $attributes = []; - /** - * Get instance of the object - * - * Let's the parent class do all the work - * - * @static - * @param string $class name of the class to instantiate - * @return object self::$instance instance of the Config class - */ - public static function getInstance($class = 'Browser') - { - return parent::getInstance($class); - } + /** + * Get instance of the object + * + * Let's the parent class do all the work + * + * @static + * @param string $class name of the class to instantiate + * @return object self::$instance instance of the Config class + */ + public static function getInstance($class = 'Browser') + { + return parent::getInstance($class); + } - /** - * Set browser variable - * - * Sets a variable in the attributes array for easier access later. - * - * @static - * @param string $variable name of the variable to set - * @param mixed $value the value to set to the variable - * @return boolean true - */ - public static function set($variable, $value) - { - $browser = Browser::getInstance(); - $browser->attributes[$variable] = $value; + /** + * Set browser variable + * + * Sets a variable in the attributes array for easier access later. + * + * @static + * @param string $variable name of the variable to set + * @param mixed $value the value to set to the variable + * @return boolean true + */ + public static function set($variable, $value) + { + $browser = Browser::getInstance(); + $browser->attributes[$variable] = $value; - return true; - } + return true; + } - /** - * Get browser variable - * - * Gets a variable passed in from the browser. Currently only supports - * the custom attribute URI format /$variable:$value/. - * - * @static - * @param string $variable name of the variable to get - * @return mixed the value of the variable or boolean false if not set - */ - public static function get($variable) - { - $browser = Browser::getInstance(); + /** + * Get browser variable + * + * Gets a variable passed in from the browser. Currently only supports + * the custom attribute URI format /$variable:$value/. + * + * @static + * @param string $variable name of the variable to get + * @return mixed the value of the variable or boolean false if not set + */ + public static function get($variable) + { + $browser = Browser::getInstance(); - if (isset($browser->attributes[$variable])) - { - return $browser->attributes[$variable]; - } + if (isset($browser->attributes[$variable])) + { + return $browser->attributes[$variable]; + } - return false; - } + return false; + } - /** - * Go Home - * - * Alias for `Browser::redirect('/');` - * - * @static - */ - public static function goHome() - { - return Browser::redirect('/'); - } + /** + * Go Home + * + * Alias for `Browser::redirect('/');` + * + * @static + */ + public static function goHome() + { + return Browser::redirect('/'); + } - /** - * Is Mobile - * - * Detects if we're working with a mobile browser. - * - * @return boolean whether or not the browser is considered mobile - */ - public static function isMobile() - { - $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; + /** + * Is Mobile + * + * Detects if we're working with a mobile browser. + * + * @return boolean whether or not the browser is considered mobile + */ + public static function isMobile() + { + $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; - return preg_match('/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $user_agent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i', substr($user_agent, 0, 4)) || strpos('iPhone', $user_agent); - } + return preg_match('/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $user_agent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i', substr($user_agent, 0, 4)) || strpos('iPhone', $user_agent); + } - /** - * Redirect - * - * Redirects the browser to another URL. Stops execution as to not run - * code erroneously due to output buffering. HTTP/1.1 request an - * absolute URI, hence the inclusion of the scheme, hostname and - * absolute path if :// is not found. Don't hate the player, hate the - * RFC. - * - * @static - * @param string $destination URL to redirect to - * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30 - */ - public static function redirect($destination) - { - if (strpos($destination, '://') === false) - { - $destination = 'http' . ((!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off' || $_SERVER['HTTPS'] == '') ? '' : 's') . '://' . $_SERVER['HTTP_HOST'] . $destination; - } + /** + * Redirect + * + * Redirects the browser to another URL. Stops execution as to not run + * code erroneously due to output buffering. HTTP/1.1 request an + * absolute URI, hence the inclusion of the scheme, hostname and + * absolute path if :// is not found. Don't hate the player, hate the + * RFC. + * + * @static + * @param string $destination URL to redirect to + * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30 + */ + public static function redirect($destination) + { + if (strpos($destination, '://') === false) + { + $destination = 'http' . ((!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off' || $_SERVER['HTTPS'] == '') ? '' : 's') . '://' . $_SERVER['HTTP_HOST'] . $destination; + } - header('Location: ' . $destination); - exit; - } + header('Location: ' . $destination); + exit; + } - /** - * Refresh - * - * Forces a browser refresh of the currently requested page. - * - * @static - */ - public static function refresh() - { - Browser::redirect($_SERVER['REQUEST_URI']); - } + /** + * Refresh + * + * Forces a browser refresh of the currently requested page. + * + * @static + */ + public static function refresh() + { + Browser::redirect($_SERVER['REQUEST_URI']); + } - /** - * Remote IP - * - * Returns the user's IP address. - * - * @return mixed IP address or false if unable to determine - */ - public static function remoteIP() - { - if (!empty($_SERVER['HTTP_CLIENT_IP'])) - { - $ip = $_SERVER['HTTP_CLIENT_IP']; - } - elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) - { - $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; - } - elseif (isset($_SERVER['REMOTE_ADDR'])) - { - $ip = $_SERVER['REMOTE_ADDR']; - } - else - { - $ip = false; - } + /** + * Remote IP + * + * Returns the user's IP address. + * + * @return mixed IP address or false if unable to determine + */ + public static function remoteIP() + { + if (!empty($_SERVER['HTTP_CLIENT_IP'])) + { + $ip = $_SERVER['HTTP_CLIENT_IP']; + } + elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) + { + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } + elseif (isset($_SERVER['REMOTE_ADDR'])) + { + $ip = $_SERVER['REMOTE_ADDR']; + } + else + { + $ip = false; + } - return $ip; - } + return $ip; + } - /** - * Status - * - * Pushes a status code to the browser. Some of these codes are site - * (420) and server (444) specific, some just for LOLs (418) and some - * that are still in draft (425) and subject to change. I wanted this - * to be a complete list and in the scenario that a code had multiple - * meanings, I favored a more recent RFC (424) even if merely a draft - * (451). - * - * @static - * @param integer status response code - */ - public static function status($code = 200) - { - switch ($code) - { - // {{{ 1xx Informational - case 100: $message = '100 Continue'; break; - case 101: $message = '101 Switching Protocols'; break; - case 102: $message = '102 Processing'; break; - // }}} - // {{{ 2xx Success - case 201: $message = '201 Created'; break; - case 202: $message = '202 Accepted'; break; - case 203: $message = '203 Non-Authoritative Information'; break; - case 204: $message = '204 No Content'; break; - case 205: $message = '205 Reset Content'; break; - case 206: $message = '206 Partial Content'; break; - case 207: $message = '207 Multi-Status'; break; - case 208: $message = '208 Already Reported'; break; - case 226: $message = '226 IM Used'; break; - // }}} - // {{{ 3xx Redirection - case 300: $message = '300 Multiple Choices'; break; - case 301: $message = '301 Moved Permanently'; break; - case 302: $message = '302 Found'; break; - case 303: $message = '303 See Other'; break; - case 304: $message = '304 Not Modified'; break; - case 305: $message = '305 Use Proxy'; break; - case 306: $message = '306 Switch Proxy'; break; - case 307: $message = '307 Temporary Redirect'; break; - case 308: $message = '308 Permanent Redirect'; break; - // }}} - // {{{ 4xx Client Error - case 400: $message = '400 Bad Request'; break; - case 401: $message = '401 Unauthorized'; break; - case 402: $message = '402 Payment Required'; break; - case 403: $message = '403 Forbidden'; break; - case 404: $message = '404 Not Found'; break; - case 405: $message = '405 Method Not Allowed'; break; - case 406: $message = '406 Not Acceptable'; break; - case 407: $message = '407 Proxy Authentication Required'; break; - case 408: $message = '408 Request Timeout'; break; - case 409: $message = '409 Conflict'; break; - case 410: $message = '410 Gone'; break; - case 411: $message = '411 Length Required'; break; - case 412: $message = '412 Precondition Failed'; break; - case 413: $message = '413 Request Entity Too Large'; break; - case 414: $message = '414 Request-URI Too Long'; break; - case 415: $message = '415 Unsupported Media Type'; break; - case 416: $message = '416 Requested Range Not Satisfied'; break; - case 417: $message = '417 Expectation Failed'; break; - case 418: $message = '418 I\'m a teapot'; break; - case 420: $message = '420 Enhance Your Calm'; break; - case 422: $message = '422 Unprocessed Entity'; break; - case 423: $message = '423 Locked'; break; - case 424: $message = '424 Failed Dependency'; break; - case 425: $message = '425 Unordered Collection'; break; - case 426: $message = '426 Upgrade Required'; break; - case 428: $message = '428 Precondition Required'; break; - case 429: $message = '429 Too Many Requests'; break; - case 431: $message = '431 Request Header Fields Too Large'; break; - case 444: $message = '444 No Response'; break; - case 449: $message = '449 Retry With'; break; - case 450: $message = '450 Blocked by Windows Parental Controls'; break; - case 451: $message = '451 Unavailable for Legal Reasons'; break; - case 494: $message = '494 Request Header Too Large'; break; - case 495: $message = '495 Cert Error'; break; - case 496: $message = '496 No Cert'; break; - case 497: $message = '497 HTTP to HTTPS'; break; - case 499: $message = '499 Client Closed Request'; break; - // }}} - // {{{ 5xx Server Error - case 500: $message = '500 Internal Server Error'; break; - case 501: $message = '501 Not Implemented'; break; - case 502: $message = '502 Bad Gateway'; break; - case 503: $message = '503 Service Unavailable'; break; - case 504: $message = '504 Gateway Timeout'; break; - case 505: $message = '505 HTTP Version Not Supported'; break; - case 506: $message = '506 Variant Also Negotiates'; break; - case 507: $message = '507 Insufficient Storage'; break; - case 508: $message = '508 Loop Detected'; break; - case 509: $message = '509 Bandwidth Limit Exceeded'; break; - case 510: $message = '510 Not Extended'; break; - case 511: $message = '511 Network Authentication Required'; break; - case 598: $message = '598 Network read timeout error'; break; - case 599: $message = '599 Network connect timeout error'; break; - // }}} - default: $message = '200 OK'; break; - } + /** + * Status + * + * Pushes a status code to the browser. Some of these codes are site + * (420) and server (444) specific, some just for LOLs (418) and some + * that are still in draft (425) and subject to change. I wanted this + * to be a complete list and in the scenario that a code had multiple + * meanings, I favored a more recent RFC (424) even if merely a draft + * (451). + * + * @static + * @param integer status response code + */ + public static function status($code = 200) + { + switch ($code) + { + // {{{ 1xx Informational + case 100: $message = '100 Continue'; break; + case 101: $message = '101 Switching Protocols'; break; + case 102: $message = '102 Processing'; break; + // }}} + // {{{ 2xx Success + case 201: $message = '201 Created'; break; + case 202: $message = '202 Accepted'; break; + case 203: $message = '203 Non-Authoritative Information'; break; + case 204: $message = '204 No Content'; break; + case 205: $message = '205 Reset Content'; break; + case 206: $message = '206 Partial Content'; break; + case 207: $message = '207 Multi-Status'; break; + case 208: $message = '208 Already Reported'; break; + case 226: $message = '226 IM Used'; break; + // }}} + // {{{ 3xx Redirection + case 300: $message = '300 Multiple Choices'; break; + case 301: $message = '301 Moved Permanently'; break; + case 302: $message = '302 Found'; break; + case 303: $message = '303 See Other'; break; + case 304: $message = '304 Not Modified'; break; + case 305: $message = '305 Use Proxy'; break; + case 306: $message = '306 Switch Proxy'; break; + case 307: $message = '307 Temporary Redirect'; break; + case 308: $message = '308 Permanent Redirect'; break; + // }}} + // {{{ 4xx Client Error + case 400: $message = '400 Bad Request'; break; + case 401: $message = '401 Unauthorized'; break; + case 402: $message = '402 Payment Required'; break; + case 403: $message = '403 Forbidden'; break; + case 404: $message = '404 Not Found'; break; + case 405: $message = '405 Method Not Allowed'; break; + case 406: $message = '406 Not Acceptable'; break; + case 407: $message = '407 Proxy Authentication Required'; break; + case 408: $message = '408 Request Timeout'; break; + case 409: $message = '409 Conflict'; break; + case 410: $message = '410 Gone'; break; + case 411: $message = '411 Length Required'; break; + case 412: $message = '412 Precondition Failed'; break; + case 413: $message = '413 Request Entity Too Large'; break; + case 414: $message = '414 Request-URI Too Long'; break; + case 415: $message = '415 Unsupported Media Type'; break; + case 416: $message = '416 Requested Range Not Satisfied'; break; + case 417: $message = '417 Expectation Failed'; break; + case 418: $message = '418 I\'m a teapot'; break; + case 420: $message = '420 Enhance Your Calm'; break; + case 422: $message = '422 Unprocessed Entity'; break; + case 423: $message = '423 Locked'; break; + case 424: $message = '424 Failed Dependency'; break; + case 425: $message = '425 Unordered Collection'; break; + case 426: $message = '426 Upgrade Required'; break; + case 428: $message = '428 Precondition Required'; break; + case 429: $message = '429 Too Many Requests'; break; + case 431: $message = '431 Request Header Fields Too Large'; break; + case 444: $message = '444 No Response'; break; + case 449: $message = '449 Retry With'; break; + case 450: $message = '450 Blocked by Windows Parental Controls'; break; + case 451: $message = '451 Unavailable for Legal Reasons'; break; + case 494: $message = '494 Request Header Too Large'; break; + case 495: $message = '495 Cert Error'; break; + case 496: $message = '496 No Cert'; break; + case 497: $message = '497 HTTP to HTTPS'; break; + case 499: $message = '499 Client Closed Request'; break; + // }}} + // {{{ 5xx Server Error + case 500: $message = '500 Internal Server Error'; break; + case 501: $message = '501 Not Implemented'; break; + case 502: $message = '502 Bad Gateway'; break; + case 503: $message = '503 Service Unavailable'; break; + case 504: $message = '504 Gateway Timeout'; break; + case 505: $message = '505 HTTP Version Not Supported'; break; + case 506: $message = '506 Variant Also Negotiates'; break; + case 507: $message = '507 Insufficient Storage'; break; + case 508: $message = '508 Loop Detected'; break; + case 509: $message = '509 Bandwidth Limit Exceeded'; break; + case 510: $message = '510 Not Extended'; break; + case 511: $message = '511 Network Authentication Required'; break; + case 598: $message = '598 Network read timeout error'; break; + case 599: $message = '599 Network connect timeout error'; break; + // }}} + default: $message = '200 OK'; break; + } - header('HTTP/1.1 ' . $message, true, $code); - header('Status: ' . $message, true, $code); - } + header('HTTP/1.1 ' . $message, true, $code); + header('Status: ' . $message, true, $code); + } } -?> diff --git a/src/classes/Cache.php b/src/classes/Cache.php index b930ae6..5a02d70 100644 --- a/src/classes/Cache.php +++ b/src/classes/Cache.php @@ -36,188 +36,187 @@ */ class Cache extends Object { - /** - * Namespace (prefix) - * - * @access private - * @var string - */ - private $namespace = ''; + /** + * Namespace (prefix) + * + * @access private + * @var string + */ + private $namespace = ''; - /** - * Servers - * - * @access private - * @var integer - */ - private $servers = 0; + /** + * Servers + * + * @access private + * @var integer + */ + private $servers = 0; - /** - * Connection resource to Memcached - * - * @access private - * @var object - */ - private $connection = null; + /** + * Connection resource to Memcached + * + * @access private + * @var object + */ + private $connection = null; - /** - * Constructor - * - * Sets up our connection variables. - * - * @param string $hostname optional hostname to connect to - * @param string $database optional port to use - */ - public function __construct() - { - parent::__construct(); + /** + * Constructor + * + * Sets up our connection variables. + * + * @param string $hostname optional hostname to connect to + * @param string $database optional port to use + */ + public function __construct() + { + parent::__construct(); - // @todo Shouldn't need the isset() but Travis is failing some tests - if (isset($this->config->pickles['cache']) && $this->config->pickles['cache']) - { - $datasources = $this->config->pickles['cache']; + // @todo Shouldn't need the isset() but Travis is failing some tests + if (isset($this->config->pickles['cache']) && $this->config->pickles['cache']) + { + $datasources = $this->config->pickles['cache']; - if (!is_array($datasources)) - { - $datasources = [$datasources]; - } + if (!is_array($datasources)) + { + $datasources = [$datasources]; + } - $this->connection = new Memcache(); + $this->connection = new Memcache(); - foreach ($datasources as $name) - { - if (isset($this->config->datasources[$name])) - { - $datasource = $this->config->datasources[$name]; + foreach ($datasources as $name) + { + if (isset($this->config->datasources[$name])) + { + $datasource = $this->config->datasources[$name]; - $this->connection->addServer($datasource['hostname'], $datasource['port']); - $this->servers++; + $this->connection->addServer($datasource['hostname'], $datasource['port']); + $this->servers++; - if (isset($datasource['namespace'])) - { - $this->namespace = $datasource['namespace']; - } - } - } - } + if (isset($datasource['namespace'])) + { + $this->namespace = $datasource['namespace']; + } + } + } + } - if ($this->namespace != '') - { - $this->namespace .= '-'; - } - } + if ($this->namespace != '') + { + $this->namespace .= '-'; + } + } - /** - * Destructor - * - * Closes the connection when the object dies. - */ - public function __destruct() - { - if ($this->servers) - { - $this->connection->close(); - } - } + /** + * Destructor + * + * Closes the connection when the object dies. + */ + public function __destruct() + { + if ($this->servers) + { + $this->connection->close(); + } + } - /** - * Get Instance - * - * Let's the parent class do all the work. - * - * @static - * @param string $class name of the class to instantiate - * @return object self::$instance instance of the Cache class - */ - public static function getInstance($class = 'Cache') - { - return parent::getInstance($class); - } + /** + * Get Instance + * + * Let's the parent class do all the work. + * + * @static + * @param string $class name of the class to instantiate + * @return object self::$instance instance of the Cache class + */ + public static function getInstance($class = 'Cache') + { + return parent::getInstance($class); + } - /** - * Get Key - * - * Gets the value of the key(s) and returns it. - * - * @param mixed $keys key(s) to retrieve - * @return mixed value(s) of the requested key(s), false if not set - */ - public function get($keys) - { - if (is_array($keys)) - { - foreach ($keys as $index => $key) - { - $keys[$index] = strtoupper($this->namespace . $key); - } - } - else - { - $keys = strtoupper($this->namespace . $keys); - } + /** + * Get Key + * + * Gets the value of the key(s) and returns it. + * + * @param mixed $keys key(s) to retrieve + * @return mixed value(s) of the requested key(s), false if not set + */ + public function get($keys) + { + if (is_array($keys)) + { + foreach ($keys as $index => $key) + { + $keys[$index] = strtoupper($this->namespace . $key); + } + } + else + { + $keys = strtoupper($this->namespace . $keys); + } - return $this->connection->get($keys); - } + return $this->connection->get($keys); + } - /** - * Set Key - * - * Sets key to the specified value. I've found that compression can lead to - * issues with integers and can slow down the storage and retrieval of data - * (defeats the purpose of caching if you ask me) and isn't supported. I've - * also been burned by data inadvertantly being cached for infinity, but - * have had great success caching data for a full day, hence defaulting the - * expiration to a full day. - * - * @param string $key key to set - * @param mixed $value value to set - * @param integer $expiration optional expiration, defaults to 1 day - * @return boolean status of writing the data to the key - */ - public function set($key, $value, $expire = Time::DAY) - { - $key = strtoupper($key); + /** + * Set Key + * + * Sets key to the specified value. I've found that compression can lead to + * issues with integers and can slow down the storage and retrieval of data + * (defeats the purpose of caching if you ask me) and isn't supported. I've + * also been burned by data inadvertantly being cached for infinity, but + * have had great success caching data for a full day, hence defaulting the + * expiration to a full day. + * + * @param string $key key to set + * @param mixed $value value to set + * @param integer $expiration optional expiration, defaults to 1 day + * @return boolean status of writing the data to the key + */ + public function set($key, $value, $expire = Time::DAY) + { + $key = strtoupper($key); - return $this->connection->set(strtoupper($this->namespace . $key), $value, 0, $expire); - } + return $this->connection->set(strtoupper($this->namespace . $key), $value, 0, $expire); + } - /** - * Delete Key - * - * Deletes the specified key(s). - * - * @param mixed $keys key(s) to delete - * @return boolean status of deleting the key - */ - public function delete($keys) - { - if (!is_array($keys)) - { - $keys = [$keys]; - } + /** + * Delete Key + * + * Deletes the specified key(s). + * + * @param mixed $keys key(s) to delete + * @return boolean status of deleting the key + */ + public function delete($keys) + { + if (!is_array($keys)) + { + $keys = [$keys]; + } - // Memcache() doesn't let you pass an array to delete all records the same way you can with get() - foreach ($keys as $key) - { - $this->connection->delete(strtoupper($this->namespace . $key)); - } + // Memcache() doesn't let you pass an array to delete all records the same way you can with get() + foreach ($keys as $key) + { + $this->connection->delete(strtoupper($this->namespace . $key)); + } - return true; - } + return true; + } - /** - * Increment Key - * - * Increments the value of an existing key. - * - * @param string $key key to increment - * @return boolean status of incrementing the key - * @todo Check if it's set as Memcache() doesn't and won't inc if it doesn't exist - */ - public function increment($key) - { - return $this->connection->increment(strtoupper($this->namespace . $key)); - } + /** + * Increment Key + * + * Increments the value of an existing key. + * + * @param string $key key to increment + * @return boolean status of incrementing the key + * @todo Check if it's set as Memcache() doesn't and won't inc if it doesn't exist + */ + public function increment($key) + { + return $this->connection->increment(strtoupper($this->namespace . $key)); + } } -?> diff --git a/src/classes/Config.php b/src/classes/Config.php index 20c07e6..3dbcfe4 100644 --- a/src/classes/Config.php +++ b/src/classes/Config.php @@ -29,228 +29,227 @@ */ class Config extends Object { - /** - * Config data - * - * @var array - */ - public $data = []; + /** + * Config data + * + * @var array + */ + public $data = []; - /** - * Constructor - * - * Calls the parent constructor and loads the passed file. - */ - public function __construct() - { - parent::__construct(); + /** + * Constructor + * + * Calls the parent constructor and loads the passed file. + */ + public function __construct() + { + parent::__construct(); - $filename = SITE_PATH . 'config.php'; - $environments = false; - $environment = false; - $is_cli = !isset($_SERVER['REQUEST_METHOD']); + $filename = SITE_PATH . 'config.php'; + $environments = false; + $environment = false; + $is_cli = !isset($_SERVER['REQUEST_METHOD']); - // Sanity checks the config file - if (file_exists($filename) && is_file($filename) && is_readable($filename)) - { - require $filename; - } + // Sanity checks the config file + if (file_exists($filename) && is_file($filename) && is_readable($filename)) + { + require $filename; + } - // Checks that we have the config array - if (isset($config)) - { - // Determines the environment - if (isset($config['environment'])) - { - $environment = $config['environment']; - } - else - { - if (isset($config['environments']) && is_array($config['environments'])) - { - $environments = $config['environments']; + // Checks that we have the config array + if (isset($config)) + { + // Determines the environment + if (isset($config['environment'])) + { + $environment = $config['environment']; + } + else + { + if (isset($config['environments']) && is_array($config['environments'])) + { + $environments = $config['environments']; - // If we're on the CLI, check an environment was even passed in - // @todo is checking for argc enough? - if ($is_cli && $_SERVER['argc'] < 2) - { - throw new Exception('You must pass an environment (e.g. php script.php )'); - } + // If we're on the CLI, check an environment was even passed in + // @todo is checking for argc enough? + if ($is_cli && $_SERVER['argc'] < 2) + { + throw new Exception('You must pass an environment (e.g. php script.php )'); + } - // Loops through the environments and tries to match on IP or name - foreach ($config['environments'] as $name => $hosts) - { - if (!is_array($hosts)) - { - $hosts = [$hosts]; - } + // Loops through the environments and tries to match on IP or name + foreach ($config['environments'] as $name => $hosts) + { + if (!is_array($hosts)) + { + $hosts = [$hosts]; + } - // Tries to determine the environment name - foreach ($hosts as $host) - { - if ($is_cli) - { - // Checks the first argument on the command line - if ($_SERVER['argv'][1] == $name) - { - $environment = $name; - break; - } - } - else - { - // Exact match - if ((preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $host) - && $_SERVER['SERVER_ADDR'] == $host) - || (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] == $host)) - { - $environment = $name; - break; - } - // Fuzzy match - elseif (substr($host,0,1) == '/' && (preg_match($host, $_SERVER['SERVER_NAME'], $matches) > 0 || preg_match($host, $_SERVER['HTTP_HOST'], $matches) > 0)) - { - $environments[$name] = $matches[0]; - $environment = $name; - $config['environments'][$name] = $matches[0]; - break; - } - } - } - } - } - } + // Tries to determine the environment name + foreach ($hosts as $host) + { + if ($is_cli) + { + // Checks the first argument on the command line + if ($_SERVER['argv'][1] == $name) + { + $environment = $name; + break; + } + } + else + { + // Exact match + if ((preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $host) + && $_SERVER['SERVER_ADDR'] == $host) + || (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] == $host)) + { + $environment = $name; + break; + } + // Fuzzy match + elseif (substr($host,0,1) == '/' && (preg_match($host, $_SERVER['SERVER_NAME'], $matches) > 0 || preg_match($host, $_SERVER['HTTP_HOST'], $matches) > 0)) + { + $environments[$name] = $matches[0]; + $environment = $name; + $config['environments'][$name] = $matches[0]; + break; + } + } + } + } + } + } - // Flattens the array based on the environment - $this->data = $this->flatten($environment, $config); + // Flattens the array based on the environment + $this->data = $this->flatten($environment, $config); - // Restore environments value - if ($environments != false) - { - $this->data['environments'] = $environments; - } + // Restore environments value + if ($environments != false) + { + $this->data['environments'] = $environments; + } - // Sets the environment if it's not set already - if (!isset($this->data['environment'])) - { - $this->data['environment'] = $environment; - } + // Sets the environment if it's not set already + if (!isset($this->data['environment'])) + { + $this->data['environment'] = $environment; + } - // Defaults profiler to true if it doesn't match an option exactly - if (isset($this->data['pickles']['profiler'])) - { - // If we have an array convert to a string - if (is_array($this->data['pickles']['profiler'])) - { - $this->data['pickles']['profiler'] = implode(',', $this->data['pickles']['profiler']); - } - } - else - { - $this->data['pickles']['profiler'] = false; - } + // Defaults profiler to true if it doesn't match an option exactly + if (isset($this->data['pickles']['profiler'])) + { + // If we have an array convert to a string + if (is_array($this->data['pickles']['profiler'])) + { + $this->data['pickles']['profiler'] = implode(',', $this->data['pickles']['profiler']); + } + } + else + { + $this->data['pickles']['profiler'] = false; + } - // Defaults expected PICKLES options to false - foreach (['cache', 'logging', 'minify'] as $variable) - { - if (!isset($this->data['pickles'][$variable])) - { - $this->data['pickles'][$variable] = false; - } - } + // Defaults expected PICKLES options to false + foreach (['cache', 'logging', 'minify'] as $variable) + { + if (!isset($this->data['pickles'][$variable])) + { + $this->data['pickles'][$variable] = false; + } + } - // Creates constants for the security levels - if (isset($this->data['security']['levels']) && is_array($this->data['security']['levels'])) - { - foreach ($this->data['security']['levels'] as $value => $name) - { - $constant = 'SECURITY_LEVEL_' . strtoupper($name); + // Creates constants for the security levels + if (isset($this->data['security']['levels']) && is_array($this->data['security']['levels'])) + { + foreach ($this->data['security']['levels'] as $value => $name) + { + $constant = 'SECURITY_LEVEL_' . strtoupper($name); - // Checks if constant is already defined, and throws an error - if (defined($constant)) - { - throw new Exception('The constant ' . $constant . ' is already defined'); - } - else - { - define($constant, $value); - } - } - } + // Checks if constant is already defined, and throws an error + if (defined($constant)) + { + throw new Exception('The constant ' . $constant . ' is already defined'); + } + else + { + define($constant, $value); + } + } + } - return true; - } + return true; + } - return false; - } + return false; + } - /** - * Flatten - * - * Flattens the configuration array around the specified environment. - * - * @param string $environment selected environment - * @param array $array configuration error to flatten - * @return array flattened configuration array - */ - public function flatten($environment, $array) - { - if (is_array($array)) - { - foreach ($array as $key => $value) - { - if (is_array($value)) - { - if (isset($value[$environment])) - { - $value = $value[$environment]; - } - else - { - $value = $this->flatten($environment, $value); - } - } + /** + * Flatten + * + * Flattens the configuration array around the specified environment. + * + * @param string $environment selected environment + * @param array $array configuration error to flatten + * @return array flattened configuration array + */ + public function flatten($environment, $array) + { + if (is_array($array)) + { + foreach ($array as $key => $value) + { + if (is_array($value)) + { + if (isset($value[$environment])) + { + $value = $value[$environment]; + } + else + { + $value = $this->flatten($environment, $value); + } + } - $array[$key] = $value; - } - } + $array[$key] = $value; + } + } - return $array; - } + return $array; + } - /** - * Get instance of the object - * - * Let's the parent class do all the work - * - * @static - * @param string $class name of the class to instantiate - * @return object self::$instance instance of the Config class - */ - public static function getInstance($class = 'Config') - { - return parent::getInstance($class); - } + /** + * Get instance of the object + * + * Let's the parent class do all the work + * + * @static + * @param string $class name of the class to instantiate + * @return object self::$instance instance of the Config class + */ + public static function getInstance($class = 'Config') + { + return parent::getInstance($class); + } - /** - * Magic Getter Method - * - * Attempts to load the config variable. If it's not set, will override - * the variable with boolean false. - * - * @param string $name name of the variable requested - * @return mixed value of the variable or boolean false - */ - public function __get($name) - { - if (!isset($this->data[$name])) - { - $this->data[$name] = false; - } + /** + * Magic Getter Method + * + * Attempts to load the config variable. If it's not set, will override + * the variable with boolean false. + * + * @param string $name name of the variable requested + * @return mixed value of the variable or boolean false + */ + public function __get($name) + { + if (!isset($this->data[$name])) + { + $this->data[$name] = false; + } - return $this->data[$name]; - } + return $this->data[$name]; + } } -?> diff --git a/src/classes/Controller.php b/src/classes/Controller.php index 9ad0c2e..38b4084 100644 --- a/src/classes/Controller.php +++ b/src/classes/Controller.php @@ -27,392 +27,394 @@ */ class Controller extends Object { - /** - * Constructor - * - * To save a few keystrokes, the Controller is executed as part of the - * constructor instead of via a method. You either want the Controller or - * you don't. - */ - public function __construct() - { - parent::__construct(); + /** + * Constructor + * + * To save a few keystrokes, the Controller is executed as part of the + * constructor instead of via a method. You either want the Controller or + * you don't. + */ + public function __construct() + { + parent::__construct(); - // Generate a generic "site down" message if the site is set to be disabled - try - { - // @todo Clean this up to be just a single sanity check - if (isset($this->config->pickles['disabled']) && $this->config->pickles['disabled']) - { - $custom_template = SITE_TEMPLATE_PATH . '__shared/maintenance.phtml'; + // Generate a generic "site down" message if the site is set to be disabled + try + { + // @todo Clean this up to be just a single sanity check + if (isset($this->config->pickles['disabled']) && $this->config->pickles['disabled']) + { + $custom_template = SITE_TEMPLATE_PATH . '__shared/maintenance.phtml'; - if (file_exists($custom_template)) - { - require_once $custom_template; - } - else - { - echo ' -

Down for Maintenance

-

' . $_SERVER['SERVER_NAME'] . ' is currently down for maintenance. Please check back in a few minutes.

-

Additionally, a custom maintenance template was not found.

-
- Powered by PICKLES - '; - } + if (file_exists($custom_template)) + { + require_once $custom_template; + } + else + { + echo ' +

Down for Maintenance

+

+ ' . $_SERVER['SERVER_NAME'] . ' is currently down for maintenance. + Please check back in a few minutes. +

+

Additionally, a custom maintenance template was not found.

+
+ Powered by PICKLES + '; + } - throw new Exception(); - } + throw new Exception(); + } - // Checks for attributes passed in the URI - if (strstr($_REQUEST['request'], ':')) - { - $parts = explode('/', $_REQUEST['request']); - $_REQUEST['request'] = ''; + // Checks for attributes passed in the URI + if (strstr($_REQUEST['request'], ':')) + { + $parts = explode('/', $_REQUEST['request']); + $_REQUEST['request'] = ''; - foreach ($parts as $part) - { - if (strstr($part, ':')) - { - list($variable, $value) = explode(':', $part); - Browser::set($variable, $value); - } - else - { - $_REQUEST['request'] .= ($_REQUEST['request'] ? '/' : '') . $part; - } - } - } + foreach ($parts as $part) + { + if (strstr($part, ':')) + { + list($variable, $value) = explode(':', $part); + Browser::set($variable, $value); + } + else + { + $_REQUEST['request'] .= ($_REQUEST['request'] ? '/' : '') . $part; + } + } + } - // Catches requests that aren't lowercase - $lowercase_request = strtolower($_REQUEST['request']); + // Catches requests that aren't lowercase + $lowercase_request = strtolower($_REQUEST['request']); - if ($_REQUEST['request'] != $lowercase_request) - { - // @todo Rework the Browser class to handle the 301 (perhaps redirect301()) to not break other code - header('Location: ' . substr_replace($_SERVER['REQUEST_URI'], $lowercase_request, 1, strlen($lowercase_request)), true, 301); - throw new Exception(); - } + if ($_REQUEST['request'] != $lowercase_request) + { + // @todo Rework the Browser class to handle the 301 (perhaps redirect301()) to not break other code + header('Location: ' . substr_replace($_SERVER['REQUEST_URI'], $lowercase_request, 1, strlen($lowercase_request)), true, 301); + throw new Exception(); + } - // Grabs the requested page - $request = $_REQUEST['request']; + // Grabs the requested page + $request = $_REQUEST['request']; - // Loads the module's information - $module_class = strtr($request, '/', '_'); - $module_filename = SITE_MODULE_PATH . $request . '.php'; - $module_exists = file_exists($module_filename); + // Loads the module's information + $module_class = strtr($request, '/', '_'); + $module_filename = SITE_MODULE_PATH . $request . '.php'; + $module_exists = file_exists($module_filename); - // Attempts to instantiate the requested module - if ($module_exists) - { - if (class_exists($module_class)) - { - $module = new $module_class; - } - } + // Attempts to instantiate the requested module + if ($module_exists) + { + if (class_exists($module_class)) + { + $module = new $module_class; + } + } - // No module instantiated, load up a generic Module - if (!isset($module)) - { - $module = new Module(); - } + // No module instantiated, load up a generic Module + if (!isset($module)) + { + $module = new Module(); + } - // Determines if we need to serve over HTTP or HTTPS - if ($module->secure == false && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) - { - header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301); - throw new Exception(); - } - elseif ($module->secure == true && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == false)) - { - header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301); - throw new Exception(); - } + // Determines if we need to serve over HTTP or HTTPS + if ($module->secure == false && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) + { + header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301); + throw new Exception(); + } + elseif ($module->secure == true && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == false)) + { + header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301); + throw new Exception(); + } - // Validates security level - if ($module->security) - { - $is_authenticated = false; + // Validates security level + if ($module->security) + { + $is_authenticated = false; - if (is_array($module->security)) - { - $module_security = $module->security; - $security_check_class = 'isLevel'; + if (is_array($module->security)) + { + $module_security = $module->security; + $security_check_class = 'isLevel'; - // Checks the type and validates it - if (isset($module_security['type'])) - { - $security_check_type = strtoupper($module_security['type']); + // Checks the type and validates it + if (isset($module_security['type'])) + { + $security_check_type = strtoupper($module_security['type']); - if (in_array($security_check_type, ['IS', 'HAS', 'BETWEEN'])) - { - $security_check_class = $security_check_type; - } + if (in_array($security_check_type, ['IS', 'HAS', 'BETWEEN'])) + { + $security_check_class = $security_check_type; + } - unset($module_security['type']); - } + unset($module_security['type']); + } - $module_security_levels = []; + $module_security_levels = []; - // If there's a level(s) key use it - foreach (['level', 'levels'] as $security_level_key) - { - if (isset($module_security[$security_level_key])) - { - if (is_array($module_security[$security_level_key])) - { - $module_security_levels = array_merge($module_security_levels, $module_security[$security_level_key]); - } - else - { - $module_security_levels[] = $module_security[$security_level_key]; - } + // If there's a level(s) key use it + foreach (['level', 'levels'] as $security_level_key) + { + if (isset($module_security[$security_level_key])) + { + if (is_array($module_security[$security_level_key])) + { + $module_security_levels = array_merge($module_security_levels, $module_security[$security_level_key]); + } + else + { + $module_security_levels[] = $module_security[$security_level_key]; + } - unset($module_security[$security_level_key]); - } - } + unset($module_security[$security_level_key]); + } + } - // Assume everything left in the array is a level and add it to the array - array_merge($module_security_levels, $module_security); - $security_level_count = count($module_security_levels); + // Assume everything left in the array is a level and add it to the array + array_merge($module_security_levels, $module_security); + $security_level_count = count($module_security_levels); - switch ($security_check_class) - { - // @todo Thinking of removing this? - case 'BETWEEN': - if ($security_level_count == 2) - { - $is_authenticated = Security::betweenLevel($module_security_levels[0], array_pop($module_security_levels)); - } - break; + switch ($security_check_class) + { + // @todo Thinking of removing this? + case 'BETWEEN': + if ($security_level_count == 2) + { + $is_authenticated = Security::betweenLevel($module_security_levels[0], array_pop($module_security_levels)); + } + break; - case 'HAS': - if ($security_level_count) - { - $is_authenticated = Security::hasLevel($module_security_levels); - } - break; + case 'HAS': + if ($security_level_count) + { + $is_authenticated = Security::hasLevel($module_security_levels); + } + break; - case 'IS': - if ($security_level_count) - { - $is_authenticated = Security::isLevel($module_security_levels); - } - break; - } - } - else - { - $is_authenticated = Security::isLevel($module->security); - } + case 'IS': + if ($security_level_count) + { + $is_authenticated = Security::isLevel($module_security_levels); + } + break; + } + } + else + { + $is_authenticated = Security::isLevel($module->security); + } - if (!$is_authenticated) - { - if ($_SERVER['REQUEST_METHOD'] == 'POST') - { - // @todo Perhaps I could force a logout / redirect to the login page - throw new Exception('{"status": "error", "message": "You are not properly authenticated, try logging out and back in."}'); - } - else - { - // Sets variable for the destination - $_SESSION['__pickles']['login']['destination'] = $_REQUEST['request'] ? $_REQUEST['request'] : '/'; + if (!$is_authenticated) + { + if ($_SERVER['REQUEST_METHOD'] == 'POST') + { + // @todo Perhaps I could force a logout / redirect to the login page + throw new Exception('{"status": "error", "message": "You are not properly authenticated, try logging out and back in."}'); + } + else + { + // Sets variable for the destination + $_SESSION['__pickles']['login']['destination'] = $_REQUEST['request'] ? $_REQUEST['request'] : '/'; - // Redirect to login page - Browser::redirect('/login'); + // Redirect to login page + Browser::redirect('/login'); - // Resolves testing error due to undefined $output - $output = ''; - } - } - } + // Resolves testing error due to undefined $output + $output = ''; + } + } + } - // Gets the profiler status - $profiler = $this->config->pickles['profiler']; - $profiler = $profiler === true || stripos($profiler, 'timers') !== false; + // Gets the profiler status + $profiler = $this->config->pickles['profiler']; + $profiler = $profiler === true || stripos($profiler, 'timers') !== false; - $default_method = '__default'; - $role_method = null; + $default_method = '__default'; + $role_method = null; - if (isset($_SESSION['__pickles']['security']['role']) && !String::isEmpty($_SESSION['__pickles']['security']['role'])) - { - $role_method = '__default_' . $_SESSION['__pickles']['security']['role']; + if (isset($_SESSION['__pickles']['security']['role']) && !String::isEmpty($_SESSION['__pickles']['security']['role'])) + { + $role_method = '__default_' . $_SESSION['__pickles']['security']['role']; - if (method_exists($module, $role_method)) - { - $default_method = $role_method; - } - } + if (method_exists($module, $role_method)) + { + $default_method = $role_method; + } + } - // Attempts to execute the default method - // @todo Seems a bit redundant, refactor - if ($default_method == $role_method || method_exists($module, $default_method)) - { - // Starts a timer before the module is executed - if ($profiler) - { - Profiler::timer('module ' . $default_method); - } + // Attempts to execute the default method + // @todo Seems a bit redundant, refactor + if ($default_method == $role_method || method_exists($module, $default_method)) + { + // Starts a timer before the module is executed + if ($profiler) + { + Profiler::timer('module ' . $default_method); + } - $valid_request = false; - $error_message = 'An unexpected error has occurred.'; + $valid_request = false; + $error_message = 'An unexpected error has occurred.'; - // Determines if the request method is valid for this request - if ($module->method) - { - if (!is_array($module->method)) - { - $module->method = [$module->method]; - } + // Determines if the request method is valid for this request + if ($module->method) + { + if (!is_array($module->method)) + { + $module->method = [$module->method]; + } - foreach ($module->method as $method) - { - if ($_SERVER['REQUEST_METHOD'] == $method) - { - $valid_request = true; - break; - } - } + foreach ($module->method as $method) + { + if ($_SERVER['REQUEST_METHOD'] == $method) + { + $valid_request = true; + break; + } + } - if (!$valid_request) - { - // @todo Should probably utilize that AJAX flag to determine the type of return - $error_message = 'There was a problem with your request method.'; - } - } - else - { - $valid_request = true; - } + if (!$valid_request) + { + // @todo Should probably utilize that AJAX flag to determine the type of return + $error_message = 'There was a problem with your request method.'; + } + } + else + { + $valid_request = true; + } - $valid_form_input = true; + $valid_form_input = true; - if ($valid_request && $module->validate) - { - $validation_errors = $module->__validate(); + if ($valid_request && $module->validate) + { + $validation_errors = $module->__validate(); - if ($validation_errors) - { - $error_message = implode(' ', $validation_errors); - $valid_form_input = false; - } - } + if ($validation_errors) + { + $error_message = implode(' ', $validation_errors); + $valid_form_input = false; + } + } - /** - * Note to Self: When building in caching will need to let the - * module know to use the cache, either passing in a variable - * or setting it on the object - */ - if ($valid_request && $valid_form_input) - { - $module_return = $module->$default_method(); + /** + * Note to Self: When building in caching will need to let the + * module know to use the cache, either passing in a variable + * or setting it on the object + */ + if ($valid_request && $valid_form_input) + { + $module_return = $module->$default_method(); - if (!is_array($module_return)) - { - $module_return = $module->return; - } - else - { - $module_return = array_merge($module_return, $module->return); - } - } + if (!is_array($module_return)) + { + $module_return = $module->return; + } + else + { + $module_return = array_merge($module_return, $module->return); + } + } - // Stops the module timer - if ($profiler) - { - Profiler::timer('module ' . $default_method); - } + // Stops the module timer + if ($profiler) + { + Profiler::timer('module ' . $default_method); + } - // Checks if we have any templates - $parent_template = $module->template; - $template_exists = $this->validateTemplates($module, $parent_template); + // Checks if we have any templates + $parent_template = $module->template; + $template_exists = $this->validateTemplates($module, $parent_template); - // No templates? 404 that shit - if (!$module_exists && !$template_exists) - { - Browser::status(404); - $_REQUEST['request'] = '__shared/404'; + // No templates? 404 that shit + if (!$module_exists && !$template_exists) + { + Browser::status(404); + $_REQUEST['request'] = '__shared/404'; - if (!$this->validateTemplates($module, $parent_template)) - { - throw new Exception(' -

Not Found

-

The requested URL /' . $request . ' was not found on this server.

-

Additionally, a custom error template was not found.

-
- Powered by PICKLES - '); - } - } + if (!$this->validateTemplates($module, $parent_template)) + { + throw new Exception(' +

Not Found

+

The requested URL /' . $request . ' was not found on this server.

+

Additionally, a custom error template was not found.

+
+ Powered by PICKLES + '); + } + } - // @todo Should simplify this, give Display direct acess to - // $module instead of all these variable assignment - $display = new Display(); - $display->output = $module->output; - $display->templates = $module->template; - $display->module = isset($module_return) ? $module_return : ['status' => 'error', 'message' => $error_message]; + // @todo Should simplify this, give Display direct acess to + // $module instead of all these variable assignment + $display = new Display(); + $display->output = $module->output; + $display->templates = $module->template; + $display->module = isset($module_return) ? $module_return : ['status' => 'error', 'message' => $error_message]; - // @todo Check for $module->meta variable first, then remove entirely when sites are updated - $display->meta = [ - 'title' => $module->title, - 'description' => $module->description, - 'keywords' => $module->keywords - ]; - } + // @todo Check for $module->meta variable first, then remove entirely when sites are updated + $display->meta = [ + 'title' => $module->title, + 'description' => $module->description, + 'keywords' => $module->keywords + ]; + } - // Starts a timer for the display rendering - if ($profiler) - { - Profiler::timer('display render'); - } + // Starts a timer for the display rendering + if ($profiler) + { + Profiler::timer('display render'); + } - // Renders the content - $output = $display->render(); + // Renders the content + $output = $display->render(); - // Stops the display timer - if ($profiler) - { - Profiler::timer('display render'); - } - } - catch (Exception $e) - { - $output = $e->getMessage(); - } + // Stops the display timer + if ($profiler) + { + Profiler::timer('display render'); + } + } + catch (Exception $e) + { + $output = $e->getMessage(); + } - echo $output; + echo $output; - // Display the Profiler's report if the stars are aligned - if ($this->config->pickles['profiler']) - { - Profiler::report(); - } - } + // Display the Profiler's report if the stars are aligned + if ($this->config->pickles['profiler']) + { + Profiler::report(); + } + } - // @todo Document me - private function validateTemplates(&$module, $parent_template) - { - $templates = [ - SITE_TEMPLATE_PATH . '__shared/' . $parent_template . '.phtml', - SITE_TEMPLATE_PATH . $_REQUEST['request'] . '.phtml', - ]; + // @todo Document me + private function validateTemplates(&$module, $parent_template) + { + $templates = [ + SITE_TEMPLATE_PATH . '__shared/' . $parent_template . '.phtml', + SITE_TEMPLATE_PATH . $_REQUEST['request'] . '.phtml', + ]; - $module->template = []; - $child_exists = file_exists($templates[1]); + $module->template = []; + $child_exists = file_exists($templates[1]); - if (file_exists($templates[0]) && $child_exists) - { - $module->template = $templates; - return true; - } - elseif ($child_exists) - { - $module->template = [$templates[1]]; - return true; - } + if (file_exists($templates[0]) && $child_exists) + { + $module->template = $templates; + return true; + } + elseif ($child_exists) + { + $module->template = [$templates[1]]; + return true; + } - return false; - } + return false; + } } -?> diff --git a/src/classes/Convert.php b/src/classes/Convert.php index b556905..4261c03 100644 --- a/src/classes/Convert.php +++ b/src/classes/Convert.php @@ -23,101 +23,100 @@ */ class Convert { - // {{{ Array to XML + // {{{ Array to XML - /** - * Array to XML - * - * Converts an array into XML tags (recursive). This method expects the - * passed array to be formatted very specifically to accomodate the fact - * that an array's format isn't quite the same as well-formed XML. - * - * Input Array = - * ['children' => [ - * 'child' => [ - * ['name' => 'Wendy Darling'], - * ['name' => 'John Darling'], - * ['name' => 'Michael Darling'], - * ], - * ]] - * - * Output XML = - * - * Wendy Darling - * John Darling - * Michael Darling - * - * - * @static - * @param array $array array to convert into XML - * @return string generated XML - */ - public static function arrayToXML($array, $format = false, $level = 0) - { - $xml = ''; + /** + * Array to XML + * + * Converts an array into XML tags (recursive). This method expects the + * passed array to be formatted very specifically to accomodate the fact + * that an array's format isn't quite the same as well-formed XML. + * + * Input Array = + * ['children' => [ + * 'child' => [ + * ['name' => 'Wendy Darling'], + * ['name' => 'John Darling'], + * ['name' => 'Michael Darling'], + * ], + * ]] + * + * Output XML = + * + * Wendy Darling + * John Darling + * Michael Darling + * + * + * @static + * @param array $array array to convert into XML + * @return string generated XML + */ + public static function arrayToXML($array, $format = false, $level = 0) + { + $xml = ''; - if (is_array($array)) - { - foreach ($array as $node => $value) - { - // Checks if the value is an array - if (is_array($value)) - { - foreach ($value as $node2 => $value2) - { - if (is_array($value2)) - { - // Nest the value if the node is an integer - $new_value = (is_int($node2) ? $value2 : [$node2 => $value2]); + if (is_array($array)) + { + foreach ($array as $node => $value) + { + // Checks if the value is an array + if (is_array($value)) + { + foreach ($value as $node2 => $value2) + { + if (is_array($value2)) + { + // Nest the value if the node is an integer + $new_value = (is_int($node2) ? $value2 : [$node2 => $value2]); - $xml .= ($format ? str_repeat("\t", $level) : ''); - $xml .= '<' . $node . '>' . ($format ? "\n" : ''); - $xml .= self::arrayToXML($new_value, $format, $level + 1); - $xml .= ($format ? str_repeat("\t", $level) : ''); - $xml .= '' . ($format ? "\n" : ''); - } - else - { - if (is_int($node2)) - { - $node2 = $node; - } + $xml .= ($format ? str_repeat("\t", $level) : ''); + $xml .= '<' . $node . '>' . ($format ? "\n" : ''); + $xml .= self::arrayToXML($new_value, $format, $level + 1); + $xml .= ($format ? str_repeat("\t", $level) : ''); + $xml .= '' . ($format ? "\n" : ''); + } + else + { + if (is_int($node2)) + { + $node2 = $node; + } - // Checks for special characters - if (htmlspecialchars($value2) != $value2) - { - $xml .= ($format ? str_repeat("\t", $level) : ''); - $xml .= '<' . $node2 . '>' . ($format ? "\n" : ''); - } - else - { - $xml .= ($format ? str_repeat("\t", $level) : ''); - $xml .= '<' . $node2 . '>' . $value2 . '' . ($format ? "\n" : ''); - } - } - } - } - else - { - // Checks for special characters - if (htmlspecialchars($value) != $value) - { - $xml .= ($format ? str_repeat("\t", $level) : ''); - $xml .= '<' . $node . '>' . ($format ? "\n" : ''); - } - else - { - $xml .= ($format ? str_repeat("\t", $level) : ''); - $xml .= '<' . $node . '>' . $value . '' . ($format ? "\n" : ''); - } - } - } - } + // Checks for special characters + if (htmlspecialchars($value2) != $value2) + { + $xml .= ($format ? str_repeat("\t", $level) : ''); + $xml .= '<' . $node2 . '>' . ($format ? "\n" : ''); + } + else + { + $xml .= ($format ? str_repeat("\t", $level) : ''); + $xml .= '<' . $node2 . '>' . $value2 . '' . ($format ? "\n" : ''); + } + } + } + } + else + { + // Checks for special characters + if (htmlspecialchars($value) != $value) + { + $xml .= ($format ? str_repeat("\t", $level) : ''); + $xml .= '<' . $node . '>' . ($format ? "\n" : ''); + } + else + { + $xml .= ($format ? str_repeat("\t", $level) : ''); + $xml .= '<' . $node . '>' . $value . '' . ($format ? "\n" : ''); + } + } + } + } - return $xml; - } + return $xml; + } - // }}} + // }}} } -?> diff --git a/src/classes/Database.php b/src/classes/Database.php index 91ea33e..82028fa 100644 --- a/src/classes/Database.php +++ b/src/classes/Database.php @@ -26,396 +26,395 @@ */ class Database extends Object { - /** - * DSN format - * - * @access protected - * @var string - */ - protected $dsn; + /** + * DSN format + * + * @access protected + * @var string + */ + protected $dsn; - /** - * PDO Attributes - * - * @access protected - * @var string - */ - protected $attributes = [ - PDO::ATTR_PERSISTENT => true, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::NULL_EMPTY_STRING => true, - ]; + /** + * PDO Attributes + * + * @access protected + * @var string + */ + protected $attributes = [ + PDO::ATTR_PERSISTENT => true, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::NULL_EMPTY_STRING => true, + ]; - /** - * Driver - * - * @var string - */ - public $driver = null; + /** + * Driver + * + * @var string + */ + public $driver = null; - /** - * Hostname for the server - * - * @var string - */ - public $hostname = 'localhost'; + /** + * Hostname for the server + * + * @var string + */ + public $hostname = 'localhost'; - /** - * Port number for the server - * - * @var integer - */ - public $port = null; + /** + * Port number for the server + * + * @var integer + */ + public $port = null; - /** - * UNIX socket for the server - * - * @var integer - */ - public $socket = null; + /** + * UNIX socket for the server + * + * @var integer + */ + public $socket = null; - /** - * Username for the server - * - * @var string - */ - public $username = null; + /** + * Username for the server + * + * @var string + */ + public $username = null; - /** - * Password for the server - * - * @var string - */ - public $password = null; + /** + * Password for the server + * + * @var string + */ + public $password = null; - /** - * Database name for the server - * - * @var string - */ - public $database = null; + /** + * Database name for the server + * + * @var string + */ + public $database = null; - /** - * Whether or not to use caching - * - * @var boolean - */ - public $cache = false; + /** + * Whether or not to use caching + * + * @var boolean + */ + public $cache = false; - /** - * Connection resource - * - * @var object - */ - public $connection = null; + /** + * Connection resource + * + * @var object + */ + public $connection = null; - /** - * Results object for the executed statement - * - * @var object - */ - public $results = null; + /** + * Results object for the executed statement + * + * @var object + */ + public $results = null; - /** - * Get Instance - * - * Instantiates a new instance of the Database class or returns the - * previously instantiated copy. - * - * @static - * @param string $datasource_name name of the datasource - * @return object instance of the class - */ - public static function getInstance($datasource_name = false) - { - $config = Config::getInstance(); + /** + * Get Instance + * + * Instantiates a new instance of the Database class or returns the + * previously instantiated copy. + * + * @static + * @param string $datasource_name name of the datasource + * @return object instance of the class + */ + public static function getInstance($datasource_name = false) + { + $config = Config::getInstance(); - // Tries to load a datasource if one wasn't specified - if (!$datasource_name) - { - if (isset($config->pickles['datasource'])) - { - $datasource_name = $config->pickles['datasource']; - } - elseif (is_array($config->datasources)) - { - $datasources = $config->datasources; + // Tries to load a datasource if one wasn't specified + if (!$datasource_name) + { + if (isset($config->pickles['datasource'])) + { + $datasource_name = $config->pickles['datasource']; + } + elseif (is_array($config->datasources)) + { + $datasources = $config->datasources; - foreach ($datasources as $name => $datasource) - { - if (isset($datasource['driver'])) - { - $datasource_name = $name; - } - } - } - } + foreach ($datasources as $name => $datasource) + { + if (isset($datasource['driver'])) + { + $datasource_name = $name; + } + } + } + } - // Attempts to validate the datasource - if ($datasource_name) - { - if (!isset(self::$instances['Database'][$datasource_name])) - { - if (!isset($config->datasources[$datasource_name])) - { - throw new Exception('The specified datasource is not defined in the config.'); - } + // Attempts to validate the datasource + if ($datasource_name) + { + if (!isset(self::$instances['Database'][$datasource_name])) + { + if (!isset($config->datasources[$datasource_name])) + { + throw new Exception('The specified datasource is not defined in the config.'); + } - $datasource = $config->datasources[$datasource_name]; + $datasource = $config->datasources[$datasource_name]; - if (!isset($datasource['driver'])) - { - throw new Exception('The specified datasource lacks a driver.'); - } + if (!isset($datasource['driver'])) + { + throw new Exception('The specified datasource lacks a driver.'); + } - $datasource['driver'] = strtolower($datasource['driver']); + $datasource['driver'] = strtolower($datasource['driver']); - // Checks the driver is legit and scrubs the name - switch ($datasource['driver']) - { - case 'pdo_mysql': - $attributes = [ - 'dsn' => 'mysql:host=[[hostname]];port=[[port]];unix_socket=[[socket]];dbname=[[database]]', - 'port' => 3306, - ]; - break; + // Checks the driver is legit and scrubs the name + switch ($datasource['driver']) + { + case 'pdo_mysql': + $attributes = [ + 'dsn' => 'mysql:host=[[hostname]];port=[[port]];unix_socket=[[socket]];dbname=[[database]]', + 'port' => 3306, + ]; + break; - case 'pdo_pgsql': - $attributes = [ - 'dsn' => 'pgsql:host=[[hostname]];port=[[port]];dbname=[[database]];user=[[username]];password=[[password]]', - 'port' => 5432, - ]; - break; + case 'pdo_pgsql': + $attributes = [ + 'dsn' => 'pgsql:host=[[hostname]];port=[[port]];dbname=[[database]];user=[[username]];password=[[password]]', + 'port' => 5432, + ]; + break; - case 'pdo_sqlite': - $attributes = ['dsn' => 'sqlite:[[hostname]]']; - break; + case 'pdo_sqlite': + $attributes = ['dsn' => 'sqlite:[[hostname]]']; + break; - default: - throw new Exception('Datasource driver "' . $datasource['driver'] . '" is invalid'); - break; - } + default: + throw new Exception('Datasource driver "' . $datasource['driver'] . '" is invalid'); + break; + } - // Instantiates our database class - $instance = new Database(); + // Instantiates our database class + $instance = new Database(); - // Sets our database parameters - if (is_array($datasource)) - { - $datasource = array_merge($attributes, $datasource); + // Sets our database parameters + if (is_array($datasource)) + { + $datasource = array_merge($attributes, $datasource); - foreach ($datasource as $variable => $value) - { - $instance->$variable = $value; - } - } + foreach ($datasource as $variable => $value) + { + $instance->$variable = $value; + } + } - // Caches the instance for possible reuse later - self::$instances['Database'][$datasource_name] = $instance; - } + // Caches the instance for possible reuse later + self::$instances['Database'][$datasource_name] = $instance; + } - // Returns the instance - return self::$instances['Database'][$datasource_name]; - } + // Returns the instance + return self::$instances['Database'][$datasource_name]; + } - return false; - } + return false; + } - /** - * Opens database connection - * - * Establishes a connection to the database based on the set configuration - * options. - * - * @return boolean true on success, throws an exception overwise - */ - public function open() - { - if ($this->connection === null) - { - switch ($this->driver) - { - case 'pdo_mysql': - // Resolves "Invalid UTF-8 sequence" issues when encoding as JSON - // @todo Didn't resolve that issue, borked some other characters though - //$this->attributes[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8'; - break; + /** + * Opens database connection + * + * Establishes a connection to the database based on the set configuration + * options. + * + * @return boolean true on success, throws an exception overwise + */ + public function open() + { + if ($this->connection === null) + { + switch ($this->driver) + { + case 'pdo_mysql': + // Resolves "Invalid UTF-8 sequence" issues when encoding as JSON + // @todo Didn't resolve that issue, borked some other characters though + //$this->attributes[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8'; + break; - case 'pdo_pgsql': - // This combats a bug: https://bugs.php.net/bug.php?id=62571&edit=1 - $this->attributes[PDO::ATTR_PERSISTENT] = false; + case 'pdo_pgsql': + // This combats a bug: https://bugs.php.net/bug.php?id=62571&edit=1 + $this->attributes[PDO::ATTR_PERSISTENT] = false; - // This allows for multiple prepared queries - $this->attributes[PDO::ATTR_EMULATE_PREPARES] = true; - break; - } + // This allows for multiple prepared queries + $this->attributes[PDO::ATTR_EMULATE_PREPARES] = true; + break; + } - if (isset($this->username, $this->password, $this->database)) - { - // Swaps out any variables with values in the DSN - $this->dsn = str_replace( - ['[[hostname]]', '[[port]]', '[[socket]]', '[[username]]', '[[password]]', '[[database]]'], - [$this->hostname, $this->port, $this->socket, $this->username, $this->password, $this->database], - $this->dsn - ); + if (isset($this->username, $this->password, $this->database)) + { + // Swaps out any variables with values in the DSN + $this->dsn = str_replace( + ['[[hostname]]', '[[port]]', '[[socket]]', '[[username]]', '[[password]]', '[[database]]'], + [$this->hostname, $this->port, $this->socket, $this->username, $this->password, $this->database], + $this->dsn + ); - // Strips any empty parameters in the DSN - $this->dsn = str_replace(['host=;', 'port=;', 'unix_socket=;'], '', $this->dsn); + // Strips any empty parameters in the DSN + $this->dsn = str_replace(['host=;', 'port=;', 'unix_socket=;'], '', $this->dsn); - // Attempts to establish a connection - $this->connection = new PDO($this->dsn, $this->username, $this->password, $this->attributes); - } - else - { - throw new Exception('There was an error loading the database configuration.'); - } - } + // Attempts to establish a connection + $this->connection = new PDO($this->dsn, $this->username, $this->password, $this->attributes); + } + else + { + throw new Exception('There was an error loading the database configuration.'); + } + } - return true; - } + return true; + } - /** - * Closes database connection - * - * Sets the connection to null regardless of state. - * - * @return boolean always true - */ - public function close() - { - $this->connection = null; - return true; - } + /** + * Closes database connection + * + * Sets the connection to null regardless of state. + * + * @return boolean always true + */ + public function close() + { + $this->connection = null; + return true; + } - /** - * Executes an SQL Statement - * - * Executes a standard or prepared query based on passed parameters. All - * queries are logged to a file as well as timed and logged in the - * execution time is over 1 second. - * - * @param string $sql statement to execute - * @param array $input_parameters optional key/values to be bound - * @param boolean $force_slow optional, force slow query logging - * @return integer ID of the last inserted row or sequence number - */ - public function execute($sql, $input_parameters = null, $force_slow = false) - { - $this->open(); + /** + * Executes an SQL Statement + * + * Executes a standard or prepared query based on passed parameters. All + * queries are logged to a file as well as timed and logged in the + * execution time is over 1 second. + * + * @param string $sql statement to execute + * @param array $input_parameters optional key/values to be bound + * @param boolean $force_slow optional, force slow query logging + * @return integer ID of the last inserted row or sequence number + */ + public function execute($sql, $input_parameters = null, $force_slow = false) + { + $this->open(); - if (isset($this->config->pickles['logging']) && $this->config->pickles['logging']) - { - $loggable_query = $sql; + if (isset($this->config->pickles['logging']) && $this->config->pickles['logging']) + { + $loggable_query = $sql; - if ($input_parameters != null) - { - $loggable_query .= ' -- ' . json_encode($input_parameters); - } + if ($input_parameters != null) + { + $loggable_query .= ' -- ' . json_encode($input_parameters); + } - Log::query($loggable_query); - } + Log::query($loggable_query); + } - $sql = trim($sql); + $sql = trim($sql); - // Checks if the query is blank - if ($sql != '') - { - // Builds out stack trace for queries - $files = []; + // Checks if the query is blank + if ($sql != '') + { + // Builds out stack trace for queries + $files = []; - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - krsort($backtrace); + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + krsort($backtrace); - foreach ($backtrace as $file) - { - if (isset($file['class'], $file['line'])) - { - $files[] = $file['class'] . ':' . $file['line']; - } - } + foreach ($backtrace as $file) + { + if (isset($file['class'], $file['line'])) + { + $files[] = $file['class'] . ':' . $file['line']; + } + } - $sql .= "\n" . '/* [' . implode('|', $files) . '] */'; + $sql .= "\n" . '/* [' . implode('|', $files) . '] */'; - // Establishes if we're working on an EXPLAIN - if (Profiler::enabled('explains')) - { - $explain = preg_match('/^SELECT /i', $sql); - } - else - { - $explain = null; - } + // Establishes if we're working on an EXPLAIN + if (Profiler::enabled('explains')) + { + $explain = preg_match('/^SELECT /i', $sql); + } + else + { + $explain = null; + } - // Executes a standard query - if ($input_parameters === null) - { - // Explains the query - if ($explain) - { - $explain = $this->fetch('EXPLAIN ' . $sql); - } + // Executes a standard query + if ($input_parameters === null) + { + // Explains the query + if ($explain) + { + $explain = $this->fetch('EXPLAIN ' . $sql); + } - $start_time = microtime(true); - $this->results = $this->connection->query($sql); - } - // Executes a prepared statement - else - { - // Explains the query - if ($explain) - { - $explain = $this->fetch('EXPLAIN ' . $sql, $input_parameters); - } + $start_time = microtime(true); + $this->results = $this->connection->query($sql); + } + // Executes a prepared statement + else + { + // Explains the query + if ($explain) + { + $explain = $this->fetch('EXPLAIN ' . $sql, $input_parameters); + } - $start_time = microtime(true); - $this->results = $this->connection->prepare($sql); - $this->results->execute($input_parameters); - } + $start_time = microtime(true); + $this->results = $this->connection->prepare($sql); + $this->results->execute($input_parameters); + } - $end_time = microtime(true); - $duration = $end_time - $start_time; + $end_time = microtime(true); + $duration = $end_time - $start_time; - if ($duration >= 1 || $force_slow) - { - Log::slowQuery($duration . ' seconds: ' . $loggable_query); - } + if ($duration >= 1 || $force_slow) + { + Log::slowQuery($duration . ' seconds: ' . $loggable_query); + } - // Logs the information to the profiler - if (Profiler::enabled('explains', 'queries')) - { - Profiler::logQuery($sql, $input_parameters, (isset($explain) ? $explain : false), $duration); - } - } - else - { - throw new Exception('No query to execute.'); - } + // Logs the information to the profiler + if (Profiler::enabled('explains', 'queries')) + { + Profiler::logQuery($sql, $input_parameters, (isset($explain) ? $explain : false), $duration); + } + } + else + { + throw new Exception('No query to execute.'); + } - return $this->connection->lastInsertId(); - } + return $this->connection->lastInsertId(); + } - /** - * Fetch records from the database - * - * @param string $sql statement to be executed - * @param array $input_parameters optional key/values to be bound - * @param string $return_type optional type of return set - * @return mixed based on return type - */ - public function fetch($sql = null, $input_parameters = null) - { - $this->open(); + /** + * Fetch records from the database + * + * @param string $sql statement to be executed + * @param array $input_parameters optional key/values to be bound + * @param string $return_type optional type of return set + * @return mixed based on return type + */ + public function fetch($sql = null, $input_parameters = null) + { + $this->open(); - if ($sql !== null) - { - $this->execute($sql, $input_parameters); - } + if ($sql !== null) + { + $this->execute($sql, $input_parameters); + } - // Pulls the results based on the type - $results = $this->results->fetchAll(PDO::FETCH_ASSOC); + // Pulls the results based on the type + $results = $this->results->fetchAll(PDO::FETCH_ASSOC); - return $results; - } + return $results; + } } -?> diff --git a/src/classes/Date.php b/src/classes/Date.php index be07c3b..6168a26 100644 --- a/src/classes/Date.php +++ b/src/classes/Date.php @@ -23,19 +23,18 @@ */ class Date { - /** - * Age - * - * Calculates age based on the passed date. - * - * @static - * @param string $date birth / inception date - * @return integer $age number of years old - */ - public static function age($date) - { - return Time::age($date); - } + /** + * Age + * + * Calculates age based on the passed date. + * + * @static + * @param string $date birth / inception date + * @return integer $age number of years old + */ + public static function age($date) + { + return Time::age($date); + } } -?> diff --git a/src/classes/Display.php b/src/classes/Display.php index e2c693c..eca2628 100644 --- a/src/classes/Display.php +++ b/src/classes/Display.php @@ -22,183 +22,183 @@ */ class Display extends Object { - /** - * Return Type - * - * This class supports loading a PHP template, displaying JSON, XML and an - * RSS flavored XML. Inside your modules you can specify either a string or - * array. Possible values include "template", "json", "xml" and "rss". - * Default behavior is to try to load a template and fallback to displaying - * JSON. The "template" option always takes precedence when used with the - * other types. - * - * @var mixed string or array to determine how to return - */ - public $return = ['template', 'json']; + /** + * Return Type + * + * This class supports loading a PHP template, displaying JSON, XML and an + * RSS flavored XML. Inside your modules you can specify either a string or + * array. Possible values include "template", "json", "xml" and "rss". + * Default behavior is to try to load a template and fallback to displaying + * JSON. The "template" option always takes precedence when used with the + * other types. + * + * @var mixed string or array to determine how to return + */ + public $return = ['template', 'json']; - /** - * Templates - * - * Templates are found in the ./templates directory of your site. The - * template workflow is to load ./templates/__shared/index.phtml and you - * would set that template up to require $this->template, the path and - * filename for the module template (named based on the structure of the - * requested URI. Inside your module you can specify the basename of the - * parent template you would like to use or false to not use a parent - * template. - * - * @var string or boolean false the basename of the parent template - */ - public $templates = false; + /** + * Templates + * + * Templates are found in the ./templates directory of your site. The + * template workflow is to load ./templates/__shared/index.phtml and you + * would set that template up to require $this->template, the path and + * filename for the module template (named based on the structure of the + * requested URI. Inside your module you can specify the basename of the + * parent template you would like to use or false to not use a parent + * template. + * + * @var string or boolean false the basename of the parent template + */ + public $templates = false; - /** - * Meta Data - * - * An array of meta data that you want exposed to the template. Currently - * you set the meta data from inside your module using the class variables - * title, description and keywords. The newer [preferred] method is to - * set an array in your module using the meta variable using title, - * description and keywords as the keys. You can also specify any other - * meta keys in the array that you would like to be exposed to your - * templates. The meta data is only used by TEMPLATE and RSS return types. - */ - public $meta = []; + /** + * Meta Data + * + * An array of meta data that you want exposed to the template. Currently + * you set the meta data from inside your module using the class variables + * title, description and keywords. The newer [preferred] method is to + * set an array in your module using the meta variable using title, + * description and keywords as the keys. You can also specify any other + * meta keys in the array that you would like to be exposed to your + * templates. The meta data is only used by TEMPLATE and RSS return types. + */ + public $meta = []; - /** - * Module Data - * - * Any data the module returns or is assigned inside of the module will - * be available here and exposed to the template. - */ - public $module = null; + /** + * Module Data + * + * Any data the module returns or is assigned inside of the module will + * be available here and exposed to the template. + */ + public $module = null; - public function render() - { - try - { - // Starts up the buffer so we can capture it - ob_start(); + public function render() + { + try + { + // Starts up the buffer so we can capture it + ob_start(); - if (!is_array($this->return)) - { - $this->return = [$this->return]; - } + if (!is_array($this->return)) + { + $this->return = [$this->return]; + } - $return_json = $return_rss = $return_template = $return_xml = false; + $return_json = $return_rss = $return_template = $return_xml = false; - foreach ($this->return as $return) - { - $variable = 'return_' . $return; - $$variable = true; - } + foreach ($this->return as $return) + { + $variable = 'return_' . $return; + $$variable = true; + } - // Makes sure the return type is valid - if (!$return_json && !$return_rss && !$return_template && !$return_xml) - { - throw new Exception('Invalid return type.'); - } + // Makes sure the return type is valid + if (!$return_json && !$return_rss && !$return_template && !$return_xml) + { + throw new Exception('Invalid return type.'); + } - // Checks for the PHPSESSID in the query string - if (stripos($_SERVER['REQUEST_URI'], '?PHPSESSID=') === false) - { - // XHTML compliancy stuff - // @todo Wonder if this could be yanked now that we're in HTML5 land - ini_set('arg_separator.output', '&'); - ini_set('url_rewriter.tags', 'a=href,area=href,frame=src,input=src,fieldset='); + // Checks for the PHPSESSID in the query string + if (stripos($_SERVER['REQUEST_URI'], '?PHPSESSID=') === false) + { + // XHTML compliancy stuff + // @todo Wonder if this could be yanked now that we're in HTML5 land + ini_set('arg_separator.output', '&'); + ini_set('url_rewriter.tags', 'a=href,area=href,frame=src,input=src,fieldset='); - header('Content-type: text/html; charset=UTF-8'); - } - else - { - // Redirect so Google knows to index the page without the session ID - list($request_uri, $phpsessid) = explode('?PHPSESSID=', $_SERVER['REQUEST_URI'], 2); - header('HTTP/1.1 301 Moved Permanently'); - header('Location: ' . $request_uri); + header('Content-type: text/html; charset=UTF-8'); + } + else + { + // Redirect so Google knows to index the page without the session ID + list($request_uri, $phpsessid) = explode('?PHPSESSID=', $_SERVER['REQUEST_URI'], 2); + header('HTTP/1.1 301 Moved Permanently'); + header('Location: ' . $request_uri); - throw new Exception('Requested URI contains PHPSESSID, redirecting.'); - } + throw new Exception('Requested URI contains PHPSESSID, redirecting.'); + } - // @todo Derrive CSS and JS from _REQUEST['request'] no need to pass around + // @todo Derrive CSS and JS from _REQUEST['request'] no need to pass around - $loaded = false; + $loaded = false; - if ($return_template) - { - // Determines if we're using a custom class or not - $dynamic_class = (class_exists('CustomDynamic') ? 'CustomDynamic' : 'Dynamic'); - $form_class = (class_exists('CustomForm') ? 'CustomForm' : 'Form'); - $html_class = (class_exists('CustomHTML') ? 'CustomHTML' : 'HTML'); + if ($return_template) + { + // Determines if we're using a custom class or not + $dynamic_class = (class_exists('CustomDynamic') ? 'CustomDynamic' : 'Dynamic'); + $form_class = (class_exists('CustomForm') ? 'CustomForm' : 'Form'); + $html_class = (class_exists('CustomHTML') ? 'CustomHTML' : 'HTML'); - // Exposes some objects and variables to the local scope of the template - $this->request = $this->js_file = $_REQUEST['request']; - // @todo replace _ with - as it's more appropriate for CSS naming - $this->css_class = strtr($this->request, '/', '_'); + // Exposes some objects and variables to the local scope of the template + $this->request = $this->js_file = $_REQUEST['request']; + // @todo replace _ with - as it's more appropriate for CSS naming + $this->css_class = strtr($this->request, '/', '_'); - // @todo Remove the magic $__variable when all sites are ported - $__config = $this->config; - $__css_class = $this->css_class; - $__js_file = $this->js_file; - $__meta = $this->meta; - $__module = $this->module; + // @todo Remove the magic $__variable when all sites are ported + $__config = $this->config; + $__css_class = $this->css_class; + $__js_file = $this->js_file; + $__meta = $this->meta; + $__module = $this->module; - $__dynamic = $this->dynamic = new $dynamic_class(); - $__form = $this->form = new $form_class(); - $__html = $this->html = new $html_class(); + $__dynamic = $this->dynamic = new $dynamic_class(); + $__form = $this->form = new $form_class(); + $__html = $this->html = new $html_class(); - // Checks for the parent template and tries to load it - if ($this->templates) - { - $profiler = $this->config->pickles['profiler']; - $profiler = $profiler === true || stripos($profiler, 'timers') !== false; + // Checks for the parent template and tries to load it + if ($this->templates) + { + $profiler = $this->config->pickles['profiler']; + $profiler = $profiler === true || stripos($profiler, 'timers') !== false; - // Starts a timer for the loading of the template - if ($profiler) - { - Profiler::timer('loading template'); - } + // Starts a timer for the loading of the template + if ($profiler) + { + Profiler::timer('loading template'); + } - // Assigns old variable - $required_template = $this->templates[0]; - $__template = $this->template = end($this->templates); - $loaded = require_once $required_template; + // Assigns old variable + $required_template = $this->templates[0]; + $__template = $this->template = end($this->templates); + $loaded = require_once $required_template; - // Stops the template loading timer - if ($profiler) - { - Profiler::timer('loading template'); - } - } - } + // Stops the template loading timer + if ($profiler) + { + Profiler::timer('loading template'); + } + } + } - if (!$loaded) - { - if ($return_json) - { - echo json_encode($this->module, isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false); - } - elseif ($return_xml) - { - echo Convert::arrayToXML($this->module, isset($_REQUEST['pretty'])); - } - } + if (!$loaded) + { + if ($return_json) + { + $pretty = isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false; + echo json_encode($this->module, $pretty); + } + elseif ($return_xml) + { + echo Convert::arrayToXML($this->module, isset($_REQUEST['pretty'])); + } + } - // Grabs the buffer so we can massage it a bit - $buffer = ob_get_clean(); + // Grabs the buffer so we can massage it a bit + $buffer = ob_get_clean(); - // Kills any whitespace and HTML comments in templates - if ($loaded) - { - // The BSA exception is because their system sucks and demands there be comments present - $buffer = preg_replace(['/^[\s]+/m', '//U'], '', $buffer); - } + // Kills any whitespace and HTML comments in templates + if ($loaded) + { + // The BSA exception is because their system sucks and demands there be comments present + $buffer = preg_replace(['/^[\s]+/m', '//U'], '', $buffer); + } - return $buffer; - } - catch (Exception $e) - { - return $e->getMessage(); - } - } + return $buffer; + } + catch (Exception $e) + { + return $e->getMessage(); + } + } } -?> diff --git a/src/classes/Distance.php b/src/classes/Distance.php index 550a931..d079228 100644 --- a/src/classes/Distance.php +++ b/src/classes/Distance.php @@ -23,122 +23,121 @@ */ class Distance { - // {{{ Call Static + // {{{ Call Static - /** - * Call Static - * - * Magic method to power the unit conversion without much code. - * - * @static - * @param string $method name of the static method being called - * @param array $arguments array of the passed arguments - * @return mixed converted units or false - */ - public static function __callStatic($method, $arguments) - { - $pieces = explode('to', strtolower($method)); + /** + * Call Static + * + * Magic method to power the unit conversion without much code. + * + * @static + * @param string $method name of the static method being called + * @param array $arguments array of the passed arguments + * @return mixed converted units or false + */ + public static function __callStatic($method, $arguments) + { + $pieces = explode('to', strtolower($method)); - if (count($pieces) == 2 && $pieces[1]) - { - return Distance::convertUnit($arguments[0], $pieces[0], $pieces[1]); - } + if (count($pieces) == 2 && $pieces[1]) + { + return Distance::convertUnit($arguments[0], $pieces[0], $pieces[1]); + } - return false; - } + return false; + } - // }}} - // {{{ Convert Unit + // }}} + // {{{ Convert Unit - /** - * Convert Unit - * - * Converts a distance from one unit to another. - * - * @static - * @param mixed $distance starting distance - * @param string $from starting unit - * @param string $to ending unit - * @return mixed - */ - private static function convertUnit($distance, $from, $to) - { - $multiplier = 1; + /** + * Convert Unit + * + * Converts a distance from one unit to another. + * + * @static + * @param mixed $distance starting distance + * @param string $from starting unit + * @param string $to ending unit + * @return mixed + */ + private static function convertUnit($distance, $from, $to) + { + $multiplier = 1; - switch ($from) - { - case 'kilometers': - switch ($to) - { - case 'miles': $multiplier = 0.621371; break; - case 'meters': $multiplier = 1000; break; - case 'yards': $multiplier = 1093.61; break; - } - break; + switch ($from) + { + case 'kilometers': + switch ($to) + { + case 'miles': $multiplier = 0.621371; break; + case 'meters': $multiplier = 1000; break; + case 'yards': $multiplier = 1093.61; break; + } + break; - case 'miles': - switch ($to) - { - case 'kilometers': $multiplier = 1.60934; break; - case 'meters': $multiplier = 1609.34; break; - case 'yards': $multiplier = 1760; break; - } - break; + case 'miles': + switch ($to) + { + case 'kilometers': $multiplier = 1.60934; break; + case 'meters': $multiplier = 1609.34; break; + case 'yards': $multiplier = 1760; break; + } + break; - case 'meters': - switch ($to) - { - case 'kilometers': $multiplier = 0.001; break; - case 'miles': $multiplier = 0.000621371; break; - case 'yards': $multiplier = 1.09361; break; - } - break; - } + case 'meters': + switch ($to) + { + case 'kilometers': $multiplier = 0.001; break; + case 'miles': $multiplier = 0.000621371; break; + case 'yards': $multiplier = 1.09361; break; + } + break; + } - return $distance * $multiplier; - } + return $distance * $multiplier; + } - // }}} - // {{{ Calculate Distance + // }}} + // {{{ Calculate Distance - /** - * Calculate Distance - * - * Calculates the distance between two sets of coordinates and returns the - * requested units. I really wanted to call this distance() but it seems - * you can't do that in PHP due to the backwards compatibility of the - * PHP4 constructors that were named the same as the class. - * - * @static - * @param mixed $latitude_from starting latitude - * @param mixed $longitude_from starting longitude - * @param mixed $latitude_to ending latitude - * @param mixed $longitude_to ending longitude - * @param string $unit optional units to return, miles by default - * @return mixed distance between the points in the desired unit - */ - public static function calculateDistance($latitude_from, $longitude_from, $latitude_to, $longitude_to, $unit = 'miles') - { - $unit = ucwords(strtolower($unit)); - $theta = $longitude_from - $longitude_to; + /** + * Calculate Distance + * + * Calculates the distance between two sets of coordinates and returns the + * requested units. I really wanted to call this distance() but it seems + * you can't do that in PHP due to the backwards compatibility of the + * PHP4 constructors that were named the same as the class. + * + * @static + * @param mixed $latitude_from starting latitude + * @param mixed $longitude_from starting longitude + * @param mixed $latitude_to ending latitude + * @param mixed $longitude_to ending longitude + * @param string $unit optional units to return, miles by default + * @return mixed distance between the points in the desired unit + */ + public static function calculateDistance($latitude_from, $longitude_from, $latitude_to, $longitude_to, $unit = 'miles') + { + $unit = ucwords(strtolower($unit)); + $theta = $longitude_from - $longitude_to; - $distance = - sin(deg2rad($latitude_from)) - * sin(deg2rad($latitude_to)) - + cos(deg2rad($latitude_from)) - * cos(deg2rad($latitude_to)) - * cos(deg2rad($theta)); + $distance = + sin(deg2rad($latitude_from)) + * sin(deg2rad($latitude_to)) + + cos(deg2rad($latitude_from)) + * cos(deg2rad($latitude_to)) + * cos(deg2rad($theta)); - $distance = acos($distance); - $distance = rad2deg($distance); - $miles = $distance * 60 * 1.1515; + $distance = acos($distance); + $distance = rad2deg($distance); + $miles = $distance * 60 * 1.1515; - $method = 'milesTo' . $unit; + $method = 'milesTo' . $unit; - return Distance::$method($miles); - } + return Distance::$method($miles); + } - // }}} + // }}} } -?> diff --git a/src/classes/Dynamic.php b/src/classes/Dynamic.php index a4de036..fa974d6 100644 --- a/src/classes/Dynamic.php +++ b/src/classes/Dynamic.php @@ -28,240 +28,239 @@ */ class Dynamic extends Object { - /** - * Generate Reference - * - * Appends a dynamic piece of information to the passed reference in the - * form of a UNIX timestamp added to the query string. - * - * @param string $reference URI reference of the file - * @param string $failover URI reference to use if the reference can't be found - * @return string URI reference reference with dynamic content - */ - public function reference($reference, $failover = false) - { - // Checks if the URI reference is absolute, and not relative - if (substr($reference, 0, 1) == '/') - { - $query_string = ''; + /** + * Generate Reference + * + * Appends a dynamic piece of information to the passed reference in the + * form of a UNIX timestamp added to the query string. + * + * @param string $reference URI reference of the file + * @param string $failover URI reference to use if the reference can't be found + * @return string URI reference reference with dynamic content + */ + public function reference($reference, $failover = false) + { + // Checks if the URI reference is absolute, and not relative + if (substr($reference, 0, 1) == '/') + { + $query_string = ''; - // Checks for ? and extracts query string - if (strstr($reference, '?')) - { - list($reference, $query_string) = explode('?', $reference); - } + // Checks for ? and extracts query string + if (strstr($reference, '?')) + { + list($reference, $query_string) = explode('?', $reference); + } - // Adds the dot so the file functions can find the file - $file = '.' . $reference; + // Adds the dot so the file functions can find the file + $file = '.' . $reference; - if (file_exists($file)) - { - // Replaces the extension with time().extension - $parts = explode('.', $reference); + if (file_exists($file)) + { + // Replaces the extension with time().extension + $parts = explode('.', $reference); - if (count($parts) == 1) - { - throw new Exception('Filename must have an extension (e.g. /path/to/file.png)'); - } - else - { - end($parts); - $parts[key($parts)] = filemtime($file) . '.' . current($parts); - $reference = implode('.', $parts); - } + if (count($parts) == 1) + { + throw new Exception('Filename must have an extension (e.g. /path/to/file.png)'); + } + else + { + end($parts); + $parts[key($parts)] = filemtime($file) . '.' . current($parts); + $reference = implode('.', $parts); + } - // Adds the query string back - if ($query_string != '') - { - $reference .= '?' . $query_string; - } - } - else - { - if ($failover != false) - { - $reference = $failover; - } - else - { - throw new Exception('Supplied reference does not exist (' . $reference . ')'); - } - } - } - else - { - throw new Exception('Reference value must be absolute (e.g. /path/to/file.png)'); - } + // Adds the query string back + if ($query_string != '') + { + $reference .= '?' . $query_string; + } + } + else + { + if ($failover != false) + { + $reference = $failover; + } + else + { + throw new Exception('Supplied reference does not exist (' . $reference . ')'); + } + } + } + else + { + throw new Exception('Reference value must be absolute (e.g. /path/to/file.png)'); + } - return $reference; - } + return $reference; + } - /** - * Generate Stylesheet Reference - * - * Attempts to minify the stylesheet and then returns the reference URI for - * the file, minified or not. Supports LESS and SASS, pass it a .less file - * or a .scss file instead and it will be compiled before minification. - * - * @param string $reference URI reference of the Stylesheet - * @return string URI reference reference with dynamic content - * @url http://lesscss.org - * @url http://sass-lang.com - */ - public function css($original_reference) - { - $less = false; - $sass = false; + /** + * Generate Stylesheet Reference + * + * Attempts to minify the stylesheet and then returns the reference URI for + * the file, minified or not. Supports LESS and SASS, pass it a .less file + * or a .scss file instead and it will be compiled before minification. + * + * @param string $reference URI reference of the Stylesheet + * @return string URI reference reference with dynamic content + * @url http://lesscss.org + * @url http://sass-lang.com + */ + public function css($original_reference) + { + $less = false; + $sass = false; - // Injects .min into the filename - $parts = explode('.', $original_reference); + // Injects .min into the filename + $parts = explode('.', $original_reference); - if (count($parts) == 1) - { - throw new Exception('Filename must have an extension (e.g. /path/to/file.css)'); - } - else - { - end($parts); + if (count($parts) == 1) + { + throw new Exception('Filename must have an extension (e.g. /path/to/file.css)'); + } + else + { + end($parts); - switch (current($parts)) - { - case 'less': - $less = true; - $parts[key($parts)] = 'css'; - break; + switch (current($parts)) + { + case 'less': + $less = true; + $parts[key($parts)] = 'css'; + break; - case 'scss': - $sass = true; - $parts[key($parts)] = 'css'; - break; - } + case 'scss': + $sass = true; + $parts[key($parts)] = 'css'; + break; + } - $parts[key($parts)] = 'min.' . current($parts); - $minified_reference = implode('.', $parts); - } + $parts[key($parts)] = 'min.' . current($parts); + $minified_reference = implode('.', $parts); + } - $original_filename = '.' . $original_reference; - $minified_filename = '.' . $minified_reference; + $original_filename = '.' . $original_reference; + $minified_filename = '.' . $minified_reference; - $path = dirname($original_filename); + $path = dirname($original_filename); - if (file_exists($original_filename)) - { - $reference = $original_reference; + if (file_exists($original_filename)) + { + $reference = $original_reference; - if ($this->config->pickles['minify'] === true) - { - // Compiles LESS & SASS to CSS before minifying - if ($less || $sass) - { - $compiled_filename = str_replace('.min', '', $minified_filename); + if ($this->config->pickles['minify'] === true) + { + // Compiles LESS & SASS to CSS before minifying + if ($less || $sass) + { + $compiled_filename = str_replace('.min', '', $minified_filename); - if ($less) - { - $less = new lessc(); - $less->compileFile($original_filename, $compiled_filename); - } - elseif ($sass) - { - $scss = new Leafo\ScssPhp\Compiler(); + if ($less) + { + $less = new lessc(); + $less->compileFile($original_filename, $compiled_filename); + } + elseif ($sass) + { + $scss = new Leafo\ScssPhp\Compiler(); - file_put_contents( - $compiled_filename, - $scss->compile(file_get_contents($original_filename)) - ); - } + file_put_contents( + $compiled_filename, + $scss->compile(file_get_contents($original_filename)) + ); + } - $original_filename = $compiled_filename; - } + $original_filename = $compiled_filename; + } - // Minifies CSS with a few basic character replacements. - $stylesheet = file_get_contents($original_filename); - $stylesheet = str_replace( - ["\t", "\n", ', ', ' {', ': ', ';}', '{ ', '; '], - ['', '', ',', '{', ':', '}', '{', ';'], - $stylesheet - ); - $stylesheet = preg_replace('/\/\*.+?\*\//', '', $stylesheet); - file_put_contents($minified_filename, $stylesheet); + // Minifies CSS with a few basic character replacements. + $stylesheet = file_get_contents($original_filename); + $stylesheet = str_replace( + ["\t", "\n", ', ', ' {', ': ', ';}', '{ ', '; '], + ['', '', ',', '{', ':', '}', '{', ';'], + $stylesheet + ); + $stylesheet = preg_replace('/\/\*.+?\*\//', '', $stylesheet); + file_put_contents($minified_filename, $stylesheet); - $reference = $minified_reference; - } - elseif (file_exists($minified_filename)) - { - $reference = $minified_reference; - } + $reference = $minified_reference; + } + elseif (file_exists($minified_filename)) + { + $reference = $minified_reference; + } - $reference = $this->reference($reference); - } - else - { - throw new Exception('Supplied reference does not exist'); - } + $reference = $this->reference($reference); + } + else + { + throw new Exception('Supplied reference does not exist'); + } - return $reference; - } + return $reference; + } - /** - * Generate Javascript Reference - * - * Attempts to minify the source with Google's Closure compiler, and then - * returns the reference URI for the file, minified or not. - * - * @link http://code.google.com/closure/compiler/ - * @param string $reference URI reference of the Javascript file - * @return string URI reference reference with dynamic content - */ - public function js($original_reference) - { - // Injects .min into the filename - $parts = explode('.', $original_reference); + /** + * Generate Javascript Reference + * + * Attempts to minify the source with Google's Closure compiler, and then + * returns the reference URI for the file, minified or not. + * + * @link http://code.google.com/closure/compiler/ + * @param string $reference URI reference of the Javascript file + * @return string URI reference reference with dynamic content + */ + public function js($original_reference) + { + // Injects .min into the filename + $parts = explode('.', $original_reference); - if (count($parts) == 1) - { - throw new Exception('Filename must have an extension (e.g. /path/to/file.js)'); - } - else - { - end($parts); - $parts[key($parts)] = 'min.' . current($parts); - $minified_reference = implode('.', $parts); - } + if (count($parts) == 1) + { + throw new Exception('Filename must have an extension (e.g. /path/to/file.js)'); + } + else + { + end($parts); + $parts[key($parts)] = 'min.' . current($parts); + $minified_reference = implode('.', $parts); + } - $original_filename = '.' . $original_reference; - $minified_filename = '.' . $minified_reference; + $original_filename = '.' . $original_reference; + $minified_filename = '.' . $minified_reference; - $path = dirname($original_filename); + $path = dirname($original_filename); - if (file_exists($original_filename)) - { - $reference = $original_reference; + if (file_exists($original_filename)) + { + $reference = $original_reference; - if ($this->config->pickles['minify'] === true) - { - $compiler = new Devize\ClosureCompiler\ClosureCompiler(); - $compiler->setSourceBaseDir(dirname($original_filename)); - $compiler->setTargetBaseDir(dirname($minified_filename)); - $compiler->addSourceFile(basename($original_filename)); - $compiler->setTargetFile(basename($minified_filename)); - $compiler->compile(); + if ($this->config->pickles['minify'] === true) + { + $compiler = new Devize\ClosureCompiler\ClosureCompiler(); + $compiler->setSourceBaseDir(dirname($original_filename)); + $compiler->setTargetBaseDir(dirname($minified_filename)); + $compiler->addSourceFile(basename($original_filename)); + $compiler->setTargetFile(basename($minified_filename)); + $compiler->compile(); - $reference = $minified_reference; - } - elseif (file_exists($minified_filename)) - { - $reference = $minified_reference; - } + $reference = $minified_reference; + } + elseif (file_exists($minified_filename)) + { + $reference = $minified_reference; + } - $reference = $this->reference($reference); - } - else - { - throw new Exception('Supplied reference does not exist'); - } + $reference = $this->reference($reference); + } + else + { + throw new Exception('Supplied reference does not exist'); + } - return $reference; - } + return $reference; + } } -?> diff --git a/src/classes/File.php b/src/classes/File.php index 82e8970..585303f 100644 --- a/src/classes/File.php +++ b/src/classes/File.php @@ -23,52 +23,51 @@ */ class File { - /** - * Remove a Directory, Recursively - * - * Removes a directory by emptying all of the contents recursively and then - * removing the directory, as PHP will not let you rmdir() on ain non-empty - * directory. Use with caution, seriously. - * - * @static - * @param string $directory directory to remove - * @return boolean status of the final rmdir(); - */ - public static function removeDirectory($directory) - { - if (substr($directory, -1) != '/') - { - $directory .= '/'; - } + /** + * Remove a Directory, Recursively + * + * Removes a directory by emptying all of the contents recursively and then + * removing the directory, as PHP will not let you rmdir() on ain non-empty + * directory. Use with caution, seriously. + * + * @static + * @param string $directory directory to remove + * @return boolean status of the final rmdir(); + */ + public static function removeDirectory($directory) + { + if (substr($directory, -1) != '/') + { + $directory .= '/'; + } - // If directory is a directory, read in all the files - if (is_dir($directory)) - { - $files = scandir($directory); + // If directory is a directory, read in all the files + if (is_dir($directory)) + { + $files = scandir($directory); - // Loop through said files, check for directories, and unlink files - foreach ($files as $file) - { - if (!in_array($file, ['.', '..'])) - { - if (is_dir($directory . $file)) - { - File::removeDirectory($directory . $file); - } - else - { - unlink($directory . $file); - } - } - } + // Loop through said files, check for directories, and unlink files + foreach ($files as $file) + { + if (!in_array($file, ['.', '..'])) + { + if (is_dir($directory . $file)) + { + File::removeDirectory($directory . $file); + } + else + { + unlink($directory . $file); + } + } + } - rmdir($directory); - } - else - { - unlink($directory); - } - } + rmdir($directory); + } + else + { + unlink($directory); + } + } } -?> diff --git a/src/classes/Form.php b/src/classes/Form.php index 3fc9f3d..100a162 100644 --- a/src/classes/Form.php +++ b/src/classes/Form.php @@ -25,649 +25,648 @@ */ class Form extends Object { - // {{{ Get Instance - - /** - * Get Instance - * - * Gets an instance of the Form class - * - * @static - * @param string $class name of the class to get an instance of - * @return object instance of the class - */ - public static function getInstance($class = 'Form') - { - return parent::getInstance($class); - } - - // }}} - // {{{ Input - - /** - * Input - * - * Generates an input with the passed data. - * - * @param string $name name (and ID) for the element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @param string $type optional type of input - * @param boolean $checked optional whether the input is checked - * @return string HTML for the input - */ - public function input($name, $value = null, $classes = null, $additional = null, $type = 'text', $checked = false) - { - if ($additional) - { - $additional = ' ' . $additional; - } - - if (in_array($type, ['checkbox', 'radio']) && $checked == true) - { - $additional .= ' checked="checked"'; - } - - if ($value) - { - $additional .= ' value="' . $value . '"'; - } - - if ($classes) - { - $additional .= ' class="' . $classes . '"'; - } - - return ''; - } - - // }}} - // {{{ Hidden - - /** - * Hidden - * - * Shorthand method to generate a hidden input. - * - * @param string $name name (and ID) for the element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function hidden($name, $value = null, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'hidden'); - } - - /** - * Hidden Input - * - * Shorthand method to generate a hidden input. - * - * @deprecated Use hidden() instead - * - * @param string $name name (and ID) for the element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function hiddenInput($name, $value = null, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'hidden'); - } - - // }}} - // {{{ Password - - /** - * Password - * - * Shorthand method to generate a password input. - * - * @param string $name name (and ID) for the element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function password($name, $value = null, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'password'); - } - - /** - * Password Input - * - * Shorthand method to generate a password input. - * - * @deprecated Use password() instead - * - * @param string $name name (and ID) for the element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function passwordInput($name, $value = null, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'password'); - } - - // }}} - // {{{ Submit - - /** - * Submit - * - * Shorthand method to generate a submit input (button). - * - * @param string $name name (and ID) for the input element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function submit($name, $value = null, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'submit'); - } - - /** - * Submit Input - * - * Shorthand method to generate a submit input (button). - * - * @deprecated Use submit() instead - * - * @param string $name name (and ID) for the input element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function submitInput($name, $value = null, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'submit'); - } - - // }}} - // {{{ Security - - /** - * Security - * - * Generates a hidden input with an SHA1 hash as the value. The name of the - * field is cannot be changed as this method was only intended for use with - * forms that are submitted via AJAX to provide better security. - * - * @param string $value value to hash - * @return string HTML for the input - */ - public function security($value) - { - // Returns the hidden input - return $this->hiddenInput('security_hash', Security::generateHash($value)); - } - - /** - * Security Input - * - * Generates a hidden input with an SHA1 hash as the value. The name of the - * field is cannot be changed as this method was only intended for use with - * forms that are submitted via AJAX to provide better security. - * - * @deprecated Use security() instead - * - * @param string $value value to hash - * @return string HTML for the input - */ - public function securityInput($value) - { - // Returns the hidden input - return $this->hiddenInput('security_hash', Security::generateHash($value)); - } - - // }}} - // {{{ Checkbox - - /** - * Checkbox - * - * Generates a checkbox input with the passed data. - * - * @param string $name name (and ID) for the select element - * @param string $value optional preset value - * @param boolean $checked optional whether the checkbox is checked - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function checkbox($name, $value = null, $checked = false, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'checkbox', $checked); - } - - // }}} - // {{{ Radio Button - - /** - * Radio Button - * - * Generates a radio input with the passed data. - * - * @param string $name name (and ID) for the select element - * @param string $value optional preset value - * @param boolean $checked optional whether the checkbox is checked - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the input - */ - public function radio($name, $value = null, $checked = false, $classes = null, $additional = null) - { - return $this->input($name, $value, $classes, $additional, 'radio', $checked); - } - - // }}} - // {{{ Textarea - - /** - * Textarea - * - * Generates a textarea with the passed data. - * - * @param string $name name (and ID) for the select element - * @param string $value optional preset value - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @param string $type optional type of input - * @return string HTML for the input - */ - public function textarea($name, $value = null, $classes = null, $additional = null) - { - if ($additional) - { - $additional = ' ' . $additional; - } - - if ($classes) - { - $additional .= ' class="' . $classes . '"'; - } - - return ''; - } - - // }}} - // {{{ Select - - /** - * Select - * - * Generates a select box with the passed data. - * - * @param string $name name (and ID) for the select element - * @param array $options key/values for the option elements - * @param string $selected optional selected option - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the select box - */ - public function select($name, $options, $selected = null, $classes = null, $additional = null) - { - if ($additional) - { - $additional = ' ' . $additional; - } - - if ($classes) - { - $additional .= ' class="' . $classes . '"'; - } - - return ''; - } - - // }}} - // {{{ Options - - /** - * Options - * - * Generates the option elements from the passed array - * - * @param array $options key/values for the options - * @param string $selected optional default option - * @return string HTML for the options - */ - public function options($options, $selected = null) - { - $found_selected = false; - $options_html = ''; - - if (is_array($options)) - { - foreach ($options as $main_key => $main_label) - { - if (is_array($main_label)) - { - $options_html .= ''; - - foreach ($main_label as $sub_key => $sub_label) - { - $selected_attribute = false; - if ($selected !== null && $found_selected === false) - { - if ($selected == $sub_key) - { - $selected_attribute = ' selected="selected"'; - $found_selected = true; - } - } - - $options_html .= ''; - } - - $options_html .= ''; - } - else - { - $selected_attribute = false; - if ($selected !== null && $found_selected === false) - { - if ($selected == $main_key) - { - $selected_attribute = ' selected="selected"'; - $found_selected = true; - } - } - - $options_html .= ''; - } - } - } - - if ($selected !== null && $found_selected === false) - { - $options_html .= ''; - } - - return $options_html; - } - - // }}} - // {{{ State Select - - /** - * State Select - * - * Generates a select box with the United States, Puerto Rico and miliary - * options - * - * @param string $name optional name (and ID) for the select element - * @param string $selected optional selected option - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the select box - */ - public function stateSelect($name = 'state', $selected = null, $classes = null, $additional = null) - { - $options = [ - null => '-- Select State --', - 'AK' => 'Alaska', - 'AL' => 'Alabama', - 'AS' => 'American Samoa', - 'AZ' => 'Arizona', - 'AR' => 'Arkansas', - 'CA' => 'California', - 'CO' => 'Colorado', - 'CT' => 'Connecticut', - 'DE' => 'Delaware', - 'DC' => 'District of Columbia', - 'FL' => 'Florida', - 'GA' => 'Georgia', - 'GU' => 'Guam', - 'HI' => 'Hawaii', - 'ID' => 'Idaho', - 'IL' => 'Illinois', - 'IN' => 'Indiana', - 'IA' => 'Iowa', - 'KS' => 'Kansas', - 'KY' => 'Kentucky', - 'LA' => 'Louisiana', - 'ME' => 'Maine', - 'MH' => 'Marshall Islands', - 'MD' => 'Maryland', - 'MA' => 'Massachusetts', - 'MI' => 'Michigan', - 'MN' => 'Minnesota', - 'MS' => 'Mississippi', - 'MO' => 'Missouri', - 'MT' => 'Montana', - 'NE' => 'Nebraska', - 'NV' => 'Nevada', - 'NH' => 'New Hampshire', - 'NJ' => 'New Jersey', - 'NM' => 'New Mexico', - 'NY' => 'New York', - 'NC' => 'North Carolina', - 'ND' => 'North Dakota', - 'MP' => 'Northern Mariana Islands', - 'OH' => 'Ohio', - 'OK' => 'Oklahoma', - 'OR' => 'Oregon', - 'PW' => 'Palau', - 'PA' => 'Pennsylvania', - 'PR' => 'Puerto Rico', - 'RI' => 'Rhode Island', - 'SC' => 'South Carolina', - 'SD' => 'South Dakota', - 'TN' => 'Tennessee', - 'TX' => 'Texas', - 'UT' => 'Utah', - 'VT' => 'Vermont', - 'VI' => 'Virgin Islands', - 'VA' => 'Virginia', - 'WA' => 'Washington', - 'WV' => 'West Virginia', - 'WI' => 'Wisconsin', - 'WY' => 'Wyoming', - 'AE' => 'Armed Forces Africa', - 'AA' => 'Armed Forces Americas (except Canada)', - 'AE' => 'Armed Forces Canada', - 'AE' => 'Armed Forces Europe', - 'AE' => 'Armed Forces Middle East', - 'AP' => 'Armed Forces Pacific' - ]; - - return $this->select($name, $options, $selected, $classes, $additional); - } - - // }}} - // {{{ Date Select - - /** - * Date Select - * - * Generates 3 select boxes (month, day, year) - * - * @param string $name optional name (and ID) for the select element - * @param string $selected optional selected option - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @param integer $start_year optional first year to display - * @param integer $end_year optional last year to display - * @return string HTML for the select boxes - */ - public function dateSelect($name = 'date', $selected = null, $classes = null, $additional = null, $start_year = null, $end_year = null) - { - $html = ''; - - // Breaks apart the selected value if present - if ($selected == null || $selected == '0000-00-00') - { - $selected_month = null; - $selected_day = null; - $selected_year = null; - } - else - { - list($selected_year, $selected_month, $selected_day) = explode('-', $selected); - } - - $month_options = [ - null => 'Month', - '01' => 'January', - '02' => 'February', - '03' => 'March', - '04' => 'April', - '05' => 'May', - '06' => 'June', - '07' => 'July', - '08' => 'August', - '09' => 'September', - '10' => 'October', - '11' => 'November', - '12' => 'December', - ]; - - $day_options = [null => 'Day']; - $year_options = [null => 'Year']; - - // Generates the list of days - for ($i = 1; $i <= 31; ++$i) - { - $day_options[str_pad($i, 2, '0', STR_PAD_LEFT)] = $i; - } - - // Generates the list of years - $current_year = date('Y'); - $start_year = $start_year == null ? $current_year - 10 : $start_year; - $end_year = $end_year == null ? $current_year + 10 : $end_year; - - for ($i = $start_year; $i >= $end_year; --$i) - { - $year_options[$i] = $i; - } - - // Loops through and generates the selects - foreach (['month', 'day', 'year'] as $part) - { - $options = $part . '_options'; - $selected = 'selected_' . $part; - $html .= ($html == '' ? '' : ' ') . $this->select($name . '[' . $part . ']', $$options, $$selected, $classes, $additional); - } - - return $html; - } - - // }}} - // {{{ Date of Birth Select - - /** - * Date of Birth Select - * - * Generates 3 select boxes (month, day, year) - * - * @param string $name optional name (and ID) for the select element - * @param string $selected optional selected option - * @param string $classes optional class names - * @param string $additional optional additional parameters - * @return string HTML for the select boxes - */ - public function dobSelect($name = 'dob', $selected = null, $classes = null, $additional = null) - { - // Note: Start year based on oldest living person: http://en.wikipedia.org/wiki/Oldest_people as of November 2010 - // Note: Start and end year may seem backwards, but we want them in descending order when rendered - return $this->dateSelect($name, $selected, $classes, $additional, date('Y'), 1896); - } - - // }}} - // {{{ Polar Select - - /** - * Polar Select - * - * Generates a polar (yes / no) select box. - * - * @param string $name optional name (and ID) for the select element - * @param string $selected optional selected option - * @param string $classes optional class names - * @param string $additional optional additional parameters - */ - public function polarSelect($name = 'decision', $selected = 0, $classes = null, $additional = null) - { - $options = [1 => 'Yes', 0 => 'No']; - - return $this->select($name, $options, $selected, $classes, $additional); - } - - // }}} - // {{{ Phone Input - - /** - * Phone Input - * - * Generates 3 inputs for a phone number from the passed values. - * - * @param string $name optional name (and ID) for the input elements - * @param string $value optional existing value - * @param string $classes optional class names - * @param string $additional optional additional parameters - */ - public function phoneInput($name = 'phone', $value = null, $classes = null, $additional = null) - { - if ($value == null) - { - $value = [ - 'area_code' => '', - 'prefix' => '', - 'line_number' => '' - ]; - } - else - { - $value = str_replace('-', '', $value); - $value = [ - 'area_code' => substr($value, 0, 3), - 'prefix' => substr($value, 3, 3), - 'line_number' => substr($value, 6) - ]; - } - - $parts = [ - 'area_code' => 3, - 'prefix' => 3, - 'line_number' => 4 - ]; - - if ($additional) - { - $additional = ' ' . $additional; - } - - $additional .= ' class="digits'; - - if ($classes) - { - $additional .= ' ' . $classes; - } - - $additional .= '"'; - - $html = ''; - foreach ($parts as $part => $size) - { - $html .= ($html != '' ? ' ' : ''); - $html .= ''; - } - - return $html; - } - - // }}} + // {{{ Get Instance + + /** + * Get Instance + * + * Gets an instance of the Form class + * + * @static + * @param string $class name of the class to get an instance of + * @return object instance of the class + */ + public static function getInstance($class = 'Form') + { + return parent::getInstance($class); + } + + // }}} + // {{{ Input + + /** + * Input + * + * Generates an input with the passed data. + * + * @param string $name name (and ID) for the element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @param string $type optional type of input + * @param boolean $checked optional whether the input is checked + * @return string HTML for the input + */ + public function input($name, $value = null, $classes = null, $additional = null, $type = 'text', $checked = false) + { + if ($additional) + { + $additional = ' ' . $additional; + } + + if (in_array($type, ['checkbox', 'radio']) && $checked == true) + { + $additional .= ' checked="checked"'; + } + + if ($value) + { + $additional .= ' value="' . $value . '"'; + } + + if ($classes) + { + $additional .= ' class="' . $classes . '"'; + } + + return ''; + } + + // }}} + // {{{ Hidden + + /** + * Hidden + * + * Shorthand method to generate a hidden input. + * + * @param string $name name (and ID) for the element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function hidden($name, $value = null, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'hidden'); + } + + /** + * Hidden Input + * + * Shorthand method to generate a hidden input. + * + * @deprecated Use hidden() instead + * + * @param string $name name (and ID) for the element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function hiddenInput($name, $value = null, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'hidden'); + } + + // }}} + // {{{ Password + + /** + * Password + * + * Shorthand method to generate a password input. + * + * @param string $name name (and ID) for the element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function password($name, $value = null, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'password'); + } + + /** + * Password Input + * + * Shorthand method to generate a password input. + * + * @deprecated Use password() instead + * + * @param string $name name (and ID) for the element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function passwordInput($name, $value = null, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'password'); + } + + // }}} + // {{{ Submit + + /** + * Submit + * + * Shorthand method to generate a submit input (button). + * + * @param string $name name (and ID) for the input element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function submit($name, $value = null, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'submit'); + } + + /** + * Submit Input + * + * Shorthand method to generate a submit input (button). + * + * @deprecated Use submit() instead + * + * @param string $name name (and ID) for the input element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function submitInput($name, $value = null, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'submit'); + } + + // }}} + // {{{ Security + + /** + * Security + * + * Generates a hidden input with an SHA1 hash as the value. The name of the + * field is cannot be changed as this method was only intended for use with + * forms that are submitted via AJAX to provide better security. + * + * @param string $value value to hash + * @return string HTML for the input + */ + public function security($value) + { + // Returns the hidden input + return $this->hiddenInput('security_hash', Security::generateHash($value)); + } + + /** + * Security Input + * + * Generates a hidden input with an SHA1 hash as the value. The name of the + * field is cannot be changed as this method was only intended for use with + * forms that are submitted via AJAX to provide better security. + * + * @deprecated Use security() instead + * + * @param string $value value to hash + * @return string HTML for the input + */ + public function securityInput($value) + { + // Returns the hidden input + return $this->hiddenInput('security_hash', Security::generateHash($value)); + } + + // }}} + // {{{ Checkbox + + /** + * Checkbox + * + * Generates a checkbox input with the passed data. + * + * @param string $name name (and ID) for the select element + * @param string $value optional preset value + * @param boolean $checked optional whether the checkbox is checked + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function checkbox($name, $value = null, $checked = false, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'checkbox', $checked); + } + + // }}} + // {{{ Radio Button + + /** + * Radio Button + * + * Generates a radio input with the passed data. + * + * @param string $name name (and ID) for the select element + * @param string $value optional preset value + * @param boolean $checked optional whether the checkbox is checked + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the input + */ + public function radio($name, $value = null, $checked = false, $classes = null, $additional = null) + { + return $this->input($name, $value, $classes, $additional, 'radio', $checked); + } + + // }}} + // {{{ Textarea + + /** + * Textarea + * + * Generates a textarea with the passed data. + * + * @param string $name name (and ID) for the select element + * @param string $value optional preset value + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @param string $type optional type of input + * @return string HTML for the input + */ + public function textarea($name, $value = null, $classes = null, $additional = null) + { + if ($additional) + { + $additional = ' ' . $additional; + } + + if ($classes) + { + $additional .= ' class="' . $classes . '"'; + } + + return ''; + } + + // }}} + // {{{ Select + + /** + * Select + * + * Generates a select box with the passed data. + * + * @param string $name name (and ID) for the select element + * @param array $options key/values for the option elements + * @param string $selected optional selected option + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the select box + */ + public function select($name, $options, $selected = null, $classes = null, $additional = null) + { + if ($additional) + { + $additional = ' ' . $additional; + } + + if ($classes) + { + $additional .= ' class="' . $classes . '"'; + } + + return ''; + } + + // }}} + // {{{ Options + + /** + * Options + * + * Generates the option elements from the passed array + * + * @param array $options key/values for the options + * @param string $selected optional default option + * @return string HTML for the options + */ + public function options($options, $selected = null) + { + $found_selected = false; + $options_html = ''; + + if (is_array($options)) + { + foreach ($options as $main_key => $main_label) + { + if (is_array($main_label)) + { + $options_html .= ''; + + foreach ($main_label as $sub_key => $sub_label) + { + $selected_attribute = false; + if ($selected !== null && $found_selected === false) + { + if ($selected == $sub_key) + { + $selected_attribute = ' selected="selected"'; + $found_selected = true; + } + } + + $options_html .= ''; + } + + $options_html .= ''; + } + else + { + $selected_attribute = false; + if ($selected !== null && $found_selected === false) + { + if ($selected == $main_key) + { + $selected_attribute = ' selected="selected"'; + $found_selected = true; + } + } + + $options_html .= ''; + } + } + } + + if ($selected !== null && $found_selected === false) + { + $options_html .= ''; + } + + return $options_html; + } + + // }}} + // {{{ State Select + + /** + * State Select + * + * Generates a select box with the United States, Puerto Rico and miliary + * options + * + * @param string $name optional name (and ID) for the select element + * @param string $selected optional selected option + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the select box + */ + public function stateSelect($name = 'state', $selected = null, $classes = null, $additional = null) + { + $options = [ + null => '-- Select State --', + 'AK' => 'Alaska', + 'AL' => 'Alabama', + 'AS' => 'American Samoa', + 'AZ' => 'Arizona', + 'AR' => 'Arkansas', + 'CA' => 'California', + 'CO' => 'Colorado', + 'CT' => 'Connecticut', + 'DE' => 'Delaware', + 'DC' => 'District of Columbia', + 'FL' => 'Florida', + 'GA' => 'Georgia', + 'GU' => 'Guam', + 'HI' => 'Hawaii', + 'ID' => 'Idaho', + 'IL' => 'Illinois', + 'IN' => 'Indiana', + 'IA' => 'Iowa', + 'KS' => 'Kansas', + 'KY' => 'Kentucky', + 'LA' => 'Louisiana', + 'ME' => 'Maine', + 'MH' => 'Marshall Islands', + 'MD' => 'Maryland', + 'MA' => 'Massachusetts', + 'MI' => 'Michigan', + 'MN' => 'Minnesota', + 'MS' => 'Mississippi', + 'MO' => 'Missouri', + 'MT' => 'Montana', + 'NE' => 'Nebraska', + 'NV' => 'Nevada', + 'NH' => 'New Hampshire', + 'NJ' => 'New Jersey', + 'NM' => 'New Mexico', + 'NY' => 'New York', + 'NC' => 'North Carolina', + 'ND' => 'North Dakota', + 'MP' => 'Northern Mariana Islands', + 'OH' => 'Ohio', + 'OK' => 'Oklahoma', + 'OR' => 'Oregon', + 'PW' => 'Palau', + 'PA' => 'Pennsylvania', + 'PR' => 'Puerto Rico', + 'RI' => 'Rhode Island', + 'SC' => 'South Carolina', + 'SD' => 'South Dakota', + 'TN' => 'Tennessee', + 'TX' => 'Texas', + 'UT' => 'Utah', + 'VT' => 'Vermont', + 'VI' => 'Virgin Islands', + 'VA' => 'Virginia', + 'WA' => 'Washington', + 'WV' => 'West Virginia', + 'WI' => 'Wisconsin', + 'WY' => 'Wyoming', + 'AE' => 'Armed Forces Africa', + 'AA' => 'Armed Forces Americas (except Canada)', + 'AE' => 'Armed Forces Canada', + 'AE' => 'Armed Forces Europe', + 'AE' => 'Armed Forces Middle East', + 'AP' => 'Armed Forces Pacific' + ]; + + return $this->select($name, $options, $selected, $classes, $additional); + } + + // }}} + // {{{ Date Select + + /** + * Date Select + * + * Generates 3 select boxes (month, day, year) + * + * @param string $name optional name (and ID) for the select element + * @param string $selected optional selected option + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @param integer $start_year optional first year to display + * @param integer $end_year optional last year to display + * @return string HTML for the select boxes + */ + public function dateSelect($name = 'date', $selected = null, $classes = null, $additional = null, $start_year = null, $end_year = null) + { + $html = ''; + + // Breaks apart the selected value if present + if ($selected == null || $selected == '0000-00-00') + { + $selected_month = null; + $selected_day = null; + $selected_year = null; + } + else + { + list($selected_year, $selected_month, $selected_day) = explode('-', $selected); + } + + $month_options = [ + null => 'Month', + '01' => 'January', + '02' => 'February', + '03' => 'March', + '04' => 'April', + '05' => 'May', + '06' => 'June', + '07' => 'July', + '08' => 'August', + '09' => 'September', + '10' => 'October', + '11' => 'November', + '12' => 'December', + ]; + + $day_options = [null => 'Day']; + $year_options = [null => 'Year']; + + // Generates the list of days + for ($i = 1; $i <= 31; ++$i) + { + $day_options[str_pad($i, 2, '0', STR_PAD_LEFT)] = $i; + } + + // Generates the list of years + $current_year = date('Y'); + $start_year = $start_year == null ? $current_year - 10 : $start_year; + $end_year = $end_year == null ? $current_year + 10 : $end_year; + + for ($i = $start_year; $i >= $end_year; --$i) + { + $year_options[$i] = $i; + } + + // Loops through and generates the selects + foreach (['month', 'day', 'year'] as $part) + { + $options = $part . '_options'; + $selected = 'selected_' . $part; + $html .= ($html == '' ? '' : ' ') . $this->select($name . '[' . $part . ']', $$options, $$selected, $classes, $additional); + } + + return $html; + } + + // }}} + // {{{ Date of Birth Select + + /** + * Date of Birth Select + * + * Generates 3 select boxes (month, day, year) + * + * @param string $name optional name (and ID) for the select element + * @param string $selected optional selected option + * @param string $classes optional class names + * @param string $additional optional additional parameters + * @return string HTML for the select boxes + */ + public function dobSelect($name = 'dob', $selected = null, $classes = null, $additional = null) + { + // Note: Start year based on oldest living person: http://en.wikipedia.org/wiki/Oldest_people as of November 2010 + // Note: Start and end year may seem backwards, but we want them in descending order when rendered + return $this->dateSelect($name, $selected, $classes, $additional, date('Y'), 1896); + } + + // }}} + // {{{ Polar Select + + /** + * Polar Select + * + * Generates a polar (yes / no) select box. + * + * @param string $name optional name (and ID) for the select element + * @param string $selected optional selected option + * @param string $classes optional class names + * @param string $additional optional additional parameters + */ + public function polarSelect($name = 'decision', $selected = 0, $classes = null, $additional = null) + { + $options = [1 => 'Yes', 0 => 'No']; + + return $this->select($name, $options, $selected, $classes, $additional); + } + + // }}} + // {{{ Phone Input + + /** + * Phone Input + * + * Generates 3 inputs for a phone number from the passed values. + * + * @param string $name optional name (and ID) for the input elements + * @param string $value optional existing value + * @param string $classes optional class names + * @param string $additional optional additional parameters + */ + public function phoneInput($name = 'phone', $value = null, $classes = null, $additional = null) + { + if ($value == null) + { + $value = [ + 'area_code' => '', + 'prefix' => '', + 'line_number' => '' + ]; + } + else + { + $value = str_replace('-', '', $value); + $value = [ + 'area_code' => substr($value, 0, 3), + 'prefix' => substr($value, 3, 3), + 'line_number' => substr($value, 6) + ]; + } + + $parts = [ + 'area_code' => 3, + 'prefix' => 3, + 'line_number' => 4 + ]; + + if ($additional) + { + $additional = ' ' . $additional; + } + + $additional .= ' class="digits'; + + if ($classes) + { + $additional .= ' ' . $classes; + } + + $additional .= '"'; + + $html = ''; + foreach ($parts as $part => $size) + { + $html .= ($html != '' ? ' ' : ''); + $html .= ''; + } + + return $html; + } + + // }}} } -?> diff --git a/src/classes/HTML.php b/src/classes/HTML.php index c8296e8..af39b32 100644 --- a/src/classes/HTML.php +++ b/src/classes/HTML.php @@ -22,128 +22,127 @@ */ class HTML extends Object { - private $self_closing = ['br', 'hr', 'img', 'input', 'link', 'meta']; + private $self_closing = ['br', 'hr', 'img', 'input', 'link', 'meta']; - public function __call($method, $arguments) - { - $attributes = null; - $contents = null; + public function __call($method, $arguments) + { + $attributes = null; + $contents = null; - if (isset($arguments[0])) - { - $attributes = $arguments[0]; - } + if (isset($arguments[0])) + { + $attributes = $arguments[0]; + } - if (isset($arguments[1])) - { - $contents = $arguments[1]; - } + if (isset($arguments[1])) + { + $contents = $arguments[1]; + } - // ->inputType('name', $attributes); - if (preg_match('/^input/', $method) && !isset($attributes['label'])) - { - $type = strtolower(str_replace('input', '', $method)); + // ->inputType('name', $attributes); + if (preg_match('/^input/', $method) && !isset($attributes['label'])) + { + $type = strtolower(str_replace('input', '', $method)); - switch ($type) - { - case 'datetimelocal': $type = 'datetime-local'; break; - case '': $type = 'text'; break; - } + switch ($type) + { + case 'datetimelocal': $type = 'datetime-local'; break; + case '': $type = 'text'; break; + } - $method = 'input'; + $method = 'input'; - if (is_array($attributes)) - { - $attributes['type'] = $type; - } - else - { - $attributes = ['type' => $type]; - } - } + if (is_array($attributes)) + { + $attributes['type'] = $type; + } + else + { + $attributes = ['type' => $type]; + } + } - if (is_array($attributes) && isset($attributes['label'])) - { - if (isset($attributes['name'])) - { - $label = $this->label(['for' => $attributes['name']], $attributes['label']); - } - else - { - $label = $this->label($attributes['label']); - } + if (is_array($attributes) && isset($attributes['label'])) + { + if (isset($attributes['name'])) + { + $label = $this->label(['for' => $attributes['name']], $attributes['label']); + } + else + { + $label = $this->label($attributes['label']); + } - unset($attributes['label']); + unset($attributes['label']); - return $label . $this->$method($attributes, $contents); - } - else - { - return $this->element($method, $attributes, $contents); - } - } + return $label . $this->$method($attributes, $contents); + } + else + { + return $this->element($method, $attributes, $contents); + } + } - // {{{ Get Instance + // {{{ Get Instance - /** - * Get Instance - * - * Gets an instance of the Form class - * - * @static - * @param string $class name of the class to get an instance of - * @return object instance of the class - */ - public static function getInstance($class = 'HTML') - { - return parent::getInstance($class); - } + /** + * Get Instance + * + * Gets an instance of the Form class + * + * @static + * @param string $class name of the class to get an instance of + * @return object instance of the class + */ + public static function getInstance($class = 'HTML') + { + return parent::getInstance($class); + } - // }}} + // }}} - public function element($element) - { - $attributes = null; - $contents = null; + public function element($element) + { + $attributes = null; + $contents = null; - foreach (func_get_args() as $key => $value) - { - if ($key && $key < 3) - { - if (is_array($value)) - { - $attributes = $value; - } - elseif ($value) - { - $contents = $value; - } - } - } + foreach (func_get_args() as $key => $value) + { + if ($key && $key < 3) + { + if (is_array($value)) + { + $attributes = $value; + } + elseif ($value) + { + $contents = $value; + } + } + } - $element = strtolower($element); - $html = '<' . $element; + $element = strtolower($element); + $html = '<' . $element; - if ($attributes) - { - if (is_array($attributes)) - { - foreach ($attributes as $attribute => $value) - { - $html .= ' ' . $attribute . '="' . str_replace('"', '\"', $value) . '"'; - } - } - } + if ($attributes) + { + if (is_array($attributes)) + { + foreach ($attributes as $attribute => $value) + { + $html .= ' ' . $attribute . '="' . str_replace('"', '\"', $value) . '"'; + } + } + } - $html .= '>'; + $html .= '>'; - if (!in_array($element, $this->self_closing)) - { - $html .= $contents . ''; - } + if (!in_array($element, $this->self_closing)) + { + $html .= $contents . ''; + } - return $html; - } + return $html; + } } -?> diff --git a/src/classes/Log.php b/src/classes/Log.php index 4e27a4e..719e682 100644 --- a/src/classes/Log.php +++ b/src/classes/Log.php @@ -22,131 +22,130 @@ */ class Log { - /** - * Log Information - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function information($message) - { - return self::write('information', $message); - } + /** + * Log Information + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function information($message) + { + return self::write('information', $message); + } - /** - * Log Warning - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function warning($message) - { - return self::write('warning', $message); - } + /** + * Log Warning + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function warning($message) + { + return self::write('warning', $message); + } - /** - * Log Error - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function error($message) - { - return self::write('error', $message); - } + /** + * Log Error + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function error($message) + { + return self::write('error', $message); + } - /** - * Log Slow Query - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function slowQuery($message) - { - return self::write('slow_query', $message); - } + /** + * Log Slow Query + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function slowQuery($message) + { + return self::write('slow_query', $message); + } - /** - * Log Credit Card Transaction - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function transaction($message) - { - return self::write('transaction', $message); - } + /** + * Log Credit Card Transaction + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function transaction($message) + { + return self::write('transaction', $message); + } - /** - * Log PHP Error - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function phpError($message, $time = false) - { - return self::write('php_error', $message, false, $time); - } + /** + * Log PHP Error + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function phpError($message, $time = false) + { + return self::write('php_error', $message, false, $time); + } - /** - * Log SQL Query - * - * @static - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - public static function query($message) - { - return self::write('query', $message); - } + /** + * Log SQL Query + * + * @static + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + public static function query($message) + { + return self::write('query', $message); + } - /** - * Write Message to Log File - * - * @static - * @access private - * @param string $message message to log - * @return boolean whether or not the write was successful - */ - private static function write($log_type, $message, $format = true, $time = false) - { - $config = Config::getInstance(); + /** + * Write Message to Log File + * + * @static + * @access private + * @param string $message message to log + * @return boolean whether or not the write was successful + */ + private static function write($log_type, $message, $format = true, $time = false) + { + $config = Config::getInstance(); - if (isset($config->pickles['logging']) && $config->pickles['logging']) - { - $log_path = LOG_PATH . date('Y/m/d/', ($time == false ? time() : $time)); + if (isset($config->pickles['logging']) && $config->pickles['logging']) + { + $log_path = LOG_PATH . date('Y/m/d/', ($time == false ? time() : $time)); - if (!file_exists($log_path)) - { - mkdir($log_path, 0755, true); - } + if (!file_exists($log_path)) + { + mkdir($log_path, 0755, true); + } - $log_file = $log_path . $log_type . '.log'; + $log_file = $log_path . $log_type . '.log'; - $message .= "\n"; + $message .= "\n"; - if ($format == true) - { - $backtrace = debug_backtrace(); - rsort($backtrace); - $frame = $backtrace[strpos($backtrace[0]['file'], 'index.php') === false ? 0 : 1]; + if ($format == true) + { + $backtrace = debug_backtrace(); + rsort($backtrace); + $frame = $backtrace[strpos($backtrace[0]['file'], 'index.php') === false ? 0 : 1]; - return file_put_contents($log_file, date('H:i:s') . ' ' . str_replace(getcwd(), '', $frame['file']) . ':' . $frame['line'] . ' ' . $message, FILE_APPEND); - } - else - { - return file_put_contents($log_file, $message, FILE_APPEND); - } - } + return file_put_contents($log_file, date('H:i:s') . ' ' . str_replace(getcwd(), '', $frame['file']) . ':' . $frame['line'] . ' ' . $message, FILE_APPEND); + } + else + { + return file_put_contents($log_file, $message, FILE_APPEND); + } + } - return false; - } + return false; + } } -?> diff --git a/src/classes/Model.php b/src/classes/Model.php index edc4337..396cd60 100644 --- a/src/classes/Model.php +++ b/src/classes/Model.php @@ -24,1538 +24,1537 @@ */ class Model extends Object { - // {{{ Properties - - /** - * Model Name - * - * @var string - */ - public $model = null; - - /** - * Columns - * - * Mapping of key columns for the table. - * - * @var array - */ - public $columns = null; - - /** - * Whether or not to use cache - * - * @var boolean - */ - public $use_cache = false; - - /** - * SQL Array - * - * @var array - */ - public $sql = []; - - /** - * Input Parameters Array - * - * @var array - */ - public $input_parameters = []; - - /** - * Insert Priority - * - * Defaults to false (normal priority) but can be set to "low" or "high" - * - * @var string - */ - public $priority = false; - - /** - * Delayed Insert - * - * @var boolean - */ - public $delayed = false; - - /** - * Ignore Unique Index - * - * @var boolean - */ - public $ignore = false; - - /** - * Replace instead of Insert/Update? - * - * @var boolean - */ - public $replace = false; - - /** - * Field List - * - * SQL: SELECT - * - * @var mixed, string or array - */ - public $fields = '*'; - - /** - * Table Name - * - * SQL: FROM - * - * @var string - */ - public $table = false; - - /** - * Conditions - * - * SQL: WHERE - * - * @var array - */ - public $conditions = false; - - /** - * Group - * - * SQL: GROUP BY - * - * @var mixed, string or array - */ - public $group = false; - - /** - * Having - * - * SQL: HAVING - * - * @var mixed, string or array - */ - public $having = false; - - /** - * Order - * - * SQL: ORDER BY - * - * @var mixed, string or array - */ - public $order = false; - - /** - * Limit - * - * SQL: LIMIT - * - * @var mixed, integer or array - */ - public $limit = false; - - /** - * Offset - * - * SQL: OFFSET - * - * @var integer - */ - public $offset = false; - - /** - * Query Results - * - * @var array - */ - public $results = null; - - /** - * Index - * - * @var integer - */ - public $index = null; - - /** - * Record - * - * @var array - */ - public $record = null; - - /** - * Records - * - * @var array - */ - public $records = null; - - /** - * Original Record - * - * @var array - */ - public $original = null; - - /** - * Iterate - * - * Used to hold the status during a walk() - * - * @var boolean - */ - public $iterate = false; - - /** - * Snapshot - * - * Snapshot of the object properties - * - * @var array - */ - public $snapshot = []; - - /** - * MySQL? - * - * Whether or not we're using MySQL - * - * @var boolean - */ - public $mysql = false; - - /** - * PostgreSQL? - * - * Whether or not we're using PostgreSQL - * - * @var boolean - */ - public $postgresql = false; - - /** - * Commit Type - * - * Indicates what we want to commit. Defaults to a single row commit, any - * calls to queue() will force the commit to process the queue. - * - * @var string - */ - public $commit_type = 'row'; - - // }}} - // {{{ Class Constructor - - /** - * Constructor - * - * Creates a new (empty) object or populates the record set. - * - * @param mixed $type_or_parameters optional type of query or parameters - * @param array $parameters optional data to create a query from - * @param string $passed_key optional key to use for caching - */ - public function __construct($type_or_parameters = null, $parameters = null, $passed_key = null) - { - // Errors if a table is not set. You're welcome, Geoff. - if ($this->table == false) - { - throw new Exception('You must set the table variable'); - } - - // Runs the parent constructor so we have the config - parent::__construct(['cache', 'db']); - - // Interrogates our database object - $this->use_cache = $this->db->cache; - $this->mysql = ($this->db->driver == 'pdo_mysql'); - $this->postgresql = ($this->db->driver == 'pdo_pgsql'); - - // Grabs the class name to use in our cache keys - $this->model = get_class($this); - - // Default column mapping - $columns = [ - 'id' => 'id', - 'created_at' => 'created_at', - 'created_id' => 'created_id', - 'updated_at' => 'updated_at', - 'updated_id' => 'updated_id', - 'deleted_at' => 'deleted_at', - 'deleted_id' => 'deleted_id', - 'is_deleted' => 'is_deleted', - ]; - - // Sets all but the `id` column to false - if ($this->columns === false) - { - foreach ($columns as $column => $field) - { - if ($column != 'id') - { - $columns[$column] = false; - } - } - } - // Merges the model's columns with the defaults - elseif (is_array($this->columns)) - { - foreach ($this->columns as $column => $field) - { - $columns[$column] = $field; - } - } - - $this->columns = $columns; - - // Takes a snapshot of the [non-object] object properties - foreach ($this as $variable => $value) - { - if (!in_array($variable, ['db', 'cache', 'config', 'snapshot'])) - { - $this->snapshot[$variable] = $value; - } - } - - return $this->execute($type_or_parameters, $parameters, $passed_key); - } - - // }}} - // {{{ Database Execution Methods - - /** - * Execute - * - * Potentially populates the record set from the passed arguments. - * - * @param mixed $type_or_parameters optional type of query or parameters - * @param mixed $parameter_or_key optional data to create query or cache key - * @param string $passed_key optional key to use for caching - */ - public function execute($type_or_parameters = null, $parameters_or_key = null, $passed_key = null) - { - // Resets internal properties - foreach ($this->snapshot as $variable => $value) - { - $this->$variable = $value; - } - - // Builds out the query - if ($type_or_parameters != null) - { - // Loads the parameters into the object - if (is_array($type_or_parameters)) - { - if (is_array($parameters_or_key)) - { - throw new Exception('You cannot pass in 2 query parameter arrays'); - } - - $this->prepareParameters($type_or_parameters); - - if ($this->use_cache - && isset($type_or_parameters['conditions'][$this->columns['id']]) - && count($type_or_parameters) == 1 - && count($type_or_parameters['conditions']) == 1) - { - $cache_keys = []; - $sorted_records = []; - - if (!is_array($type_or_parameters['conditions'][$this->columns['id']])) - { - $type_or_parameters['conditions'][$this->columns['id']] = [$type_or_parameters['conditions'][$this->columns['id']]]; - } - - foreach ($type_or_parameters['conditions'][$this->columns['id']] as $id) - { - $cache_keys[] = strtoupper($this->model) . '-' . $id; - $sorted_records[$id] = true; - } - - $cached = $this->cache->get($cache_keys); - $partial_cache = []; - - if ($cached !== false) - { - foreach ($cached as $record) - { - $partial_cache[$record['id']] = $record; - } - } - - unset($cached); - - foreach ($type_or_parameters['conditions'][$this->columns['id']] as $key => $id) - { - if (isset($partial_cache[$id])) - { - unset($type_or_parameters['conditions'][$this->columns['id']][$key]); - } - } - - if (count($type_or_parameters['conditions'][$this->columns['id']]) == 0) - { - $cache_key = true; - $cached = array_values($partial_cache); - } - } - - if ($this->columns['is_deleted']) - { - $type_or_parameters['conditions'][$this->columns['is_deleted']] = '0'; - } - - $this->loadParameters($type_or_parameters); - } - elseif (is_array($parameters_or_key)) - { - $this->prepareParameters($parameters_or_key); - - // @todo Fix cache merging to allow for this - /* - if ($this->use_cache - && isset($parameters_or_key['conditions'][$this->columns['id']]) - && count($parameters_or_key) == 1 - && count($parameters_or_key['conditions']) == 1) - { - $cache_keys = []; - $sorted_records = []; - - foreach ($parameters_or_key['conditions'][$this->columns['id']] as $id) - { - $cache_keys[] = strtoupper($this->model) . '-' . $id; - $sorted_records[$id] = true; - } - - $cached = $this->cache->get($cache_keys); - $partial_cache = []; - - if ($cached !== false) - { - foreach ($cached as $record) - { - $partial_cache[$record['id']] = $record; - } - } - - unset($cached); - - foreach ($parameters_or_key['conditions'][$this->columns['id']] as $key => $id) - { - if (isset($partial_cache[$id])) - { - unset($parameters_or_key['conditions'][$this->columns['id']][$key]); - } - } - - if (count($parameters_or_key['conditions'][$this->columns['id']]) == 0) - { - $cache_key = true; - $cached = array_values($partial_cache); - } - } - */ - - if ($this->columns['is_deleted']) - { - $parameters_or_key['conditions'][$this->columns['is_deleted']] = '0'; - } - - $this->loadParameters($parameters_or_key); - } - elseif (ctype_digit((string)$type_or_parameters)) - { - $cache_key = strtoupper($this->model) . '-' . $type_or_parameters; - $parameters_or_key = [$this->columns['id'] => $type_or_parameters]; - - if ($this->columns['is_deleted']) - { - $parameters_or_key[$this->columns['is_deleted']] = '0'; - } - - $this->loadParameters($parameters_or_key); - } - elseif (ctype_digit((string)$parameters_or_key)) - { - // @todo Fix cache merging to allow for this - //$cache_key = strtoupper($this->model) . '-' . $parameters_or_key; - - $parameters_or_key = [$this->columns['id'] => $parameters_or_key]; - - if ($this->columns['is_deleted']) - { - $parameters_or_key[$this->columns['is_deleted']] = '0'; - } - - $this->loadParameters($parameters_or_key); - } - elseif ($this->columns['is_deleted']) - { - $this->loadParameters([$this->columns['is_deleted'] => '0']); - } - - if (is_string($passed_key)) - { - $cache_key = $passed_key; - } - - // Starts with a basic SELECT ... FROM - $this->sql = [ - 'SELECT ' . (is_array($this->fields) ? implode(', ', $this->fields) : $this->fields), - 'FROM ' . $this->table, - ]; - - // Updates query to use COUNT syntax - if ($type_or_parameters == 'count') - { - $this->sql[0] = 'SELECT COUNT(*) AS count'; - $this->generateQuery(); - } - // Adds the rest of the query - elseif (!isset($cache_key) || $cache_key !== true) - { - $this->generateQuery(); - } - - if (isset($cache_key) && $this->use_cache && !isset($cached)) - { - $cached = $this->cache->get($cache_key); - } - - if (isset($cached) && $cached !== false) - { - $this->records = $cached; - } - else - { - $this->records = $this->db->fetch( - implode(' ', $this->sql), - (count($this->input_parameters) == 0 ? null : $this->input_parameters) - ); - - if (isset($partial_cache) && count($this->records)) - { - $records = array_merge($partial_cache, $this->records); - - if (isset($sorted_records)) - { - foreach ($records as $record) - { - $sorted_records[$record['id']] = $record; - } - - $records = $sorted_records; - } - - $this->records = $records; - } - - if ($this->use_cache) - { - if (isset($cache_key)) - { - if ($passed_key) - { - $cache_value = $this->records; - } - elseif (isset($this->records[0])) - { - $cache_value = $this->records[0]; - } - - // Only set the value for non-empty records. Caching - // values that are empty could be caused by querying - // records that don't exist at the moment, but could - // exist in the future. INSERTs do not do any sort of - // cache invalidation at this time. - if (isset($cache_value)) - { - $this->cache->set($cache_key, $cache_value); - } - } - elseif (isset($cache_keys)) - { - // @todo Move to Memcached extension and switch to use setMulti() - foreach ($this->records as $record) - { - if (isset($record['id'])) - { - $this->cache->set(strtoupper($this->model) . '-' . $record['id'], $record); - } - } - } - } - } - - $index_records = in_array($type_or_parameters, ['list', 'indexed']); - - // Flattens the data into a list - if ($index_records == true) - { - $list = []; - - foreach ($this->records as $record) - { - // Uses the first value as the key and the second as the value - if ($type_or_parameters == 'list') - { - $list[array_shift($record)] = array_shift($record); - } - // Uses the first value as the key - else - { - $list[current($record)] = $record; - } - } - - $this->records = $list; - } - - // Sets up the current record - if (isset($this->records[0])) - { - $this->record = $this->records[0]; - } - else - { - if ($index_records == true) - { - $this->record[key($this->records)] = current($this->records); - } - else - { - $this->record = $this->records; - } - } - - if (!preg_match('/^[0-9]+$/', implode('', array_keys($this->records)))) - { - $this->records = [$this->records]; - } - - $this->index = 0; - $this->original = $this->records; - } - - return true; - } - - // }}} - // {{{ SQL Generation Methods - - /** - * Generate Query - * - * Goes through all of the object variables that correspond with parts of - * the query and adds them to the master SQL array. - * - * @return array $this->sql an array of SQL parts - */ - public function generateQuery() - { - // Adds the WHERE conditionals - if ($this->conditions != false) - { - $use_id = true; - - foreach ($this->conditions as $column => $value) - { - if (!is_int($column)) - { - $use_id = false; - } - } - - if ($use_id) - { - $this->conditions = [$this->columns['id'] => $this->conditions]; - } - - $this->sql[] = 'WHERE ' . (is_array($this->conditions) ? $this->generateConditions($this->conditions) : $this->conditions); - } - - // Adds the GROUP BY syntax - if ($this->group != false) - { - $this->sql[] = 'GROUP BY ' . (is_array($this->group) ? implode(', ', $this->group) : $this->group); - } - - // Adds the HAVING conditions - if ($this->having != false) - { - $this->sql[] = 'HAVING ' . (is_array($this->having) ? $this->generateConditions($this->having) : $this->having); - } - - // Adds the ORDER BY syntax - if ($this->order != false) - { - $this->sql[] = 'ORDER BY ' . (is_array($this->order) ? implode(', ', $this->order) : $this->order); - } - - // Adds the LIMIT syntax - if ($this->limit != false) - { - $this->sql[] = 'LIMIT ' . (is_array($this->limit) ? implode(', ', $this->limit) : $this->limit); - } - - // Adds the OFFSET syntax - if ($this->offset != false) - { - $this->sql[] = 'OFFSET ' . $this->offset; - } - - return $this->sql; - } - - /** - * Generate Conditions - * - * Generates the conditional blocks of SQL from the passed array of - * conditions. Supports as much as I could remember to implement. This - * method is utilized by both the WHERE and HAVING clauses. - * - * @param array $conditions array of potentially nested conditions - * @param boolean $inject_values whether or not to use input parameters - * @param string $conditional syntax to use between conditions - * @return string $sql generated SQL for the conditions - */ - public function generateConditions($conditions, $inject_values = false, $conditional = 'AND') - { - $sql = ''; - - foreach ($conditions as $key => $value) - { - $key = trim($key); - - if ($sql != '') - { - if (preg_match('/^(AND|&&|OR|\|\||XOR)( NOT)?/i', $key)) - { - $sql .= ' '; - } - else - { - $sql .= ' ' . $conditional . ' '; - } - } - - // Checks for our keywords to control the flow - $operator = preg_match('/(<|<=|=|>=|>|!=|!|<>| LIKE)$/i', $key); - $between = preg_match('/ BETWEEN$/i', $key); - $is_is_not = preg_match('/( IS| IS NOT)$/i', $key); - - // Checks for boolean and null - $is_true = ($value === true); - $is_false = ($value === false); - $is_null = ($value === null); - - // Generates an in statement - if (is_array($value) && $between == false) - { - $sql .= $key . ' in ('; - - if ($inject_values == true) - { - $sql .= implode(', ', $value); - } - else - { - $sql .= implode(', ', array_fill(1, count($value), '?')); - $this->input_parameters = array_merge($this->input_parameters, $value); - } - - $sql .= ')'; - } - else - { - // If the key is numeric it wasn't set, so don't use it - if (is_numeric($key)) - { - $sql .= $value; - } - else - { - // Omits the operator as the operator is there - if ($operator == true || $is_is_not == true) - { - if ($is_true || $is_false || $is_null) - { - // Scrubs the operator if someone doesn't use IS / IS NOT - if ($operator == true) - { - $key = preg_replace('/ ?(!=|!|<>)$/i', ' IS NOT', $key); - $key = preg_replace('/ ?(<|<=|=|>=| LIKE)$/i', ' IS', $key); - } - - $sql .= $key . ' '; - - if ($is_true) - { - $sql .= 'TRUE'; - } - elseif ($is_false) - { - $sql .= 'FALSE'; - } - else - { - $sql .= 'NULL'; - } - } - else - { - $sql .= $key . ' '; - - if ($inject_values == true) - { - $sql .= $value; - } - else - { - $sql .= '?'; - $this->input_parameters[] = $value; - } - } - } - // Generates a between statement - elseif ($between == true) - { - if (is_array($value)) - { - // Checks the number of values, between expects 2 - if (count($value) != 2) - { - throw new Exception('BETWEEN expects an array with 2 values.'); - } - else - { - $sql .= $key . ' '; - - if ($inject_values == true) - { - $sql .= $value[0] . ' AND ' . $value[1]; - } - else - { - $sql .= '? AND ?'; - $this->input_parameters = array_merge($this->input_parameters, $value); - } - } - } - else - { - throw new Exception('BETWEEN expects an array.'); - } - } - else - { - $sql .= $key . ' '; - - // Checks if we're working with constants - if ($is_true) - { - $sql .= 'IS TRUE'; - } - elseif ($is_false) - { - $sql .= 'IS FALSE'; - } - elseif ($is_null) - { - $sql .= 'IS NULL'; - } - else - { - if ($inject_values == true) - { - $sql .= '= ' . $value; - } - else - { - $sql .= '= ?'; - $this->input_parameters[] = $value; - } - } - } - } - } - } - - return $sql; - } - - // }}} - // {{{ Record Interaction Methods - - /** - * Count Records - * - * Counts the records - */ - public function count() - { - if (isset($this->records[0]) && $this->records[0] == []) - { - return 0; - } - else - { - return count($this->records); - } - } - - /** - * Sort Records - * - * Sorts the records by the specified index in the specified order. - * - * @param string $index the index to be sorted on - * @param string $order the direction to order - * @return boolean true - * @todo Implement this method - */ - public function sort($index, $order = 'asc') - { - return true; - } - - /** - * Shuffle Records - * - * Sorts the records in a pseudo-random order. - * - * @return boolean true - * @todo Implement this method - */ - public function shuffle() - { - return true; - } - - /** - * Next Record - * - * Increment the record array to the next member of the record set. - * - * @return boolean whether or not there was next element - */ - public function next() - { - $return = (boolean)($this->record = next($this->records)); - - if ($return == true) - { - $this->index++; - } - - return $return; - } - - /** - * Previous Record - * - * Decrement the record array to the next member of the record set. - * - * @return boolean whether or not there was previous element - */ - public function prev() - { - $return = (boolean)($this->record = prev($this->records)); - - if ($return == true) - { - $this->index--; - } - - return $return; - } - - /** - * Reset Record - * - * Set the pointer to the first element of the record set. - * - * @return boolean whether or not records is an array (and could be reset) - */ - public function reset() - { - $return = (boolean)($this->record = reset($this->records)); - - if ($return == true) - { - $this->index = 0; - } - - return $return; - } - - /** - * First Record - * - * Alias of reset(). "first" is more intuitive to me, but reset stays in - * line with the built in PHP functions. Not sure why I'd want to add some - * consistency to one of the most inconsistent languages. - * - * @return boolean whether or not records is an array (and could be reset) - */ - public function first() - { - return $this->reset(); - } - - /** - * End Record - * - * Set the pointer to the last element of the record set. - * - * @return boolean whether or not records is an array (and end() worked) - */ - public function end() - { - $return = (boolean)($this->record = end($this->records)); - - if ($return == true) - { - $this->index = $this->count() - 1; - } - - return $return; - } - - /** - * Last record - * - * Alias of end(). "last" is more intuitive to me, but end stays in line - * with the built in PHP functions. - * - * @return boolean whether or not records is an array (and end() worked) - */ - public function last() - { - return $this->end(); - } - - /** - * Walk Records - * - * Returns the current record and advances to the next. Built to allow for - * simplified code when looping through a record set. - * - * @return mixed either an array of the current record or false - * @todo does not currently support "indexed" or "list" return types - */ - public function walk() - { - // checks if we should start iterating, solves off by one issues with next() - if ($this->iterate == false) - { - $this->iterate = true; - - // resets the records, saves calling reset() when walking multiple times - $this->reset(); - } - else - { - $this->next(); - } - - return $this->record; - } - - /** - * Queue Record - * - * Stashes the current record and creates an empty record ready to be - * manipulated. Eliminates looping through records and inserting each one - * separately and/or the need for helper methods in the models. - */ - public function queue() - { - $this->commit_type = 'queue'; - $this->records[] = $this->record; - $this->record = null; - } - - // }}} - // {{{ Record Manipulation Methods - - /** - * Commit - * - * INSERTs or UPDATEs a record in the database. - * - * @return boolean results of the query - */ - public function commit() - { - // Multiple row query / queries - if ($this->commit_type == 'queue') - { - $update = false; - $cache_keys = []; - - /** - * @todo I outta loop through twice to determine if it's an INSERT - * or an UPDATE. As it stands, you could run into a scenario - * where you could have a mixed lot that would attempt to - * build out a query with both INSERT and UPDATE syntax and - * would probably cause a doomsday scenario for our universe. - * @todo Doesn't play nice with ->walk() at all. Ends up stuck in - * an infinite loop and never executes. Could be part of the - * aforementioned doomsday scenario and fortunately PHP isn't - * letting it happen thanks to memory constraints. - */ - foreach ($this->records as $record) - { - // Performs an UPDATE with multiple queries - if (array_key_exists($this->columns['id'], $record)) - { - $update = true; - - if (!isset($sql)) - { - $sql = ''; - $input_parameters = []; - } - - $update_fields = []; - - foreach ($record as $field => $value) - { - if ($field != $this->columns['id']) - { - $update_fields[] = $field . ' = ?'; - $input_parameters[] = (is_array($value) ? json_encode($value) : $value); - } - else - { - $cache_keys[] = strtoupper($this->model) . '-' . $value; - } - } - - // @todo Check if the column was passed in - if ($this->columns['updated_at'] != false) - { - $update_fields[] = $this->columns['updated_at'] . ' = ?'; - $input_parameters[] = Time::timestamp(); - } - - // @todo Check if the column was passed in - if ($this->columns['updated_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) - { - $update_fields[] = $this->columns['updated_id'] . ' = ?'; - $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; - } - - if ($sql != '') - { - $sql .= '; '; - } - - $sql .= 'UPDATE ' . $this->table - . ' SET ' . implode(', ', $update_fields) - . ' WHERE ' . $this->columns['id'] . ' = ?'; - - $input_parameters[] = $record[$this->columns['id']]; - } - // Performs a multiple row INSERT - else - { - if (!isset($sql)) - { - $field_count = count($record); - $insert_fields = array_keys($record); - - if ($this->columns['created_at'] != false) - { - $insert_fields[] = $this->columns['created_at']; - $field_count++; - } - - if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) - { - $insert_fields[] = $this->columns['created_id']; - $field_count++; - } - - $values = '(' . implode(', ', array_fill(0, $field_count, '?')) . ')'; - $input_parameters = []; - - // INSERT INTO ... - $sql = 'INSERT INTO ' . $this->table . ' (' . implode(', ', $insert_fields) . ') VALUES ' . $values; - } - else - { - $sql .= ', ' . $values; - } - - foreach ($record as $variable => $value) - { - $input_parameters[] = (is_array($value) ? json_encode($value) : $value); - } - - // @todo Check if the column was passed in - if ($this->columns['created_at'] != false) - { - $input_parameters[] = Time::timestamp(); - } - - // @todo Check if the column was passed in - if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) - { - $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; - } - } - } - - $results = $this->db->execute($sql . ';', $input_parameters); - - // Clears the cache - if ($update && $this->use_cache) - { - $this->cache->delete($cache_keys); - } - - return $results; - } - // Single row INSERT or UPDATE - else - { - // Determines if it's an UPDATE or INSERT - $update = (isset($this->record[$this->columns['id']]) && trim($this->record[$this->columns['id']]) != ''); - - // Starts to build the query, optionally sets PRIORITY, DELAYED and IGNORE syntax - if ($this->replace === true && $this->mysql) - { - $sql = 'REPLACE'; - - if (strtoupper($this->priority) == 'LOW') - { - $sql .= ' LOW_PRIORITY'; - } - elseif ($this->delayed == true) - { - $sql .= ' DELAYED'; - } - - $sql .= ' INTO ' . $this->table; - } - else - { - if ($update == true) - { - $sql = 'UPDATE'; - } - else - { - $sql = 'INSERT'; - - // priority syntax takes priority over delayed - if ($this->mysql) - { - if ($this->priority !== false - && in_array(strtoupper($this->priority), ['LOW', 'HIGH'])) - { - $sql .= ' ' . strtoupper($this->priority) . '_PRIORITY'; - } - elseif ($this->delayed == true) - { - $sql .= ' DELAYED'; - } - - if ($this->ignore == true) - { - $sql .= ' IGNORE'; - } - } - - $sql .= ' INTO'; - } - - $sql .= ' ' . $this->table . ($update ? ' SET ' : ' '); - } - - $input_parameters = null; - - // Limits the columns being updated - $record = ($update ? array_diff_assoc( - $this->record, - isset($this->original[$this->index]) ? $this->original[$this->index] : [] - ) : $this->record); - - // Makes sure there's something to INSERT or UPDATE - if (count($record) > 0) - { - if ($this->replace && $update) - { - $update = false; - } - - $insert_fields = []; - - // Loops through all the columns and assembles the query - foreach ($record as $column => $value) - { - if ($column != $this->columns['id']) - { - if ($update == true) - { - if ($input_parameters != null) - { - $sql .= ', '; - } - - $sql .= $column . ' = '; - - if (in_array($value, ['++', '--'])) - { - $sql .= $column . ' ' . substr($value, 0, 1) . ' ?'; - $value = 1; - } - else - { - $sql .= '?'; - } - } - else - { - $insert_fields[] = $column; - } - - $input_parameters[] = (is_array($value) ? json_encode($value) : $value); - } - } - - // If it's an UPDATE tack on the ID - if ($update == true) - { - if ($this->columns['updated_at'] != false) - { - if ($input_parameters != null) - { - $sql .= ', '; - } - - $sql .= $this->columns['updated_at'] . ' = ?'; - $input_parameters[] = Time::timestamp(); - } - - if ($this->columns['updated_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) - { - if ($input_parameters != null) - { - $sql .= ', '; - } - - $sql .= $this->columns['updated_id'] . ' = ?'; - - $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; - } - - $sql .= ' WHERE ' . $this->columns['id'] . ' = ?' . ($this->mysql ? ' LIMIT 1' : '') . ';'; - $input_parameters[] = $this->record[$this->columns['id']]; - } - else - { - // @todo REPLACE should be grabbing the previous values so - // that we're not wiping out pertinent data when the - // internal columns are in use. This includes the - // `id` column that is needed to keep it from doing - // an INSERT instead of an UPDATE - if ($this->columns['created_at'] != false || $this->replace) - { - $insert_fields[] = $this->columns['created_at']; - $input_parameters[] = Time::timestamp(); - } - - if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) - { - $insert_fields[] = $this->columns['created_id']; - $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; - } - - $sql .= '(' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', array_fill(0, count($input_parameters), '?')) . ')'; - - // PDO::lastInsertID() doesn't work so we return the ID with the query - if ($this->postgresql) - { - $sql .= ' RETURNING ' . $this->columns['id']; - } - - $sql .= ';'; - } - - // Executes the query - if ($this->postgresql && $update == false) - { - return $this->db->fetch($sql, $input_parameters); - } - else - { - $results = $this->db->execute($sql, $input_parameters); - - // Clears the cache - if ($update && $this->use_cache) - { - $this->cache->delete(strtoupper($this->model) . '-' . $this->record[$this->columns['id']]); - } - - return $results; - } - } - } - - return false; - } - - /** - * Delete Record - * - * DELETEs the current record from the database. - * - * @return boolean status of the query - */ - public function delete() - { - if (isset($this->record[$this->columns['id']])) - { - // Logical deletion - if ($this->columns['is_deleted']) - { - $sql = 'UPDATE ' . $this->table . ' SET ' . $this->columns['is_deleted'] . ' = ?'; - $input_parameters = ['1']; - - if ($this->columns['deleted_at']) - { - $sql .= ', ' . $this->columns['deleted_at'] . ' = ?'; - $input_parameters[] = Time::timestamp(); - } - - if ($this->columns['deleted_id'] && isset($_SESSION['__pickles']['security']['user_id'])) - { - $sql .= ', ' . $this->columns['deleted_id'] . ' = ?'; - $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; - } - - $sql .= ' WHERE ' . $this->columns['id'] . ' = ?'; - } - // For reals deletion - else - { - $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->columns['id'] . ' = ?' . ($this->mysql ? ' LIMIT 1' : '') . ';'; - } - - $input_parameters[] = $this->record[$this->columns['id']]; - $results = $this->db->execute($sql, $input_parameters); - - // Clears the cache - if ($this->use_cache) - { - $this->cache->delete(strtoupper($this->model) . '-' . $this->record[$this->columns['id']]); - } - - return $results; - } - else - { - return false; - } - } - - // }}} - // {{{ Utility Methods - - /** - * Prepare Parameters - * - * Checks if the parameters array is only integers and reconstructs the - * array with the proper conditions format. - * - * @param array $array parameters array, passed by reference - */ - public function prepareParameters(&$parameters) - { - $all_integers = true; - - foreach ($parameters as $key => $value) - { - if (!ctype_digit((string)$key) || !ctype_digit((string)$value)) - { - $all_integers = false; - } - } - - if ($all_integers) - { - $parameters = ['conditions' => [$this->columns['id'] => $parameters]]; - } - } - - /** - * Load Parameters - * - * Loads the passed parameters back into the object. - * - * @param array $parameters key / value list - * @param boolean whether or not the parameters were loaded - */ - public function loadParameters($parameters) - { - if (is_array($parameters)) - { - $conditions = true; - - // Adds the parameters to the object - foreach ($parameters as $key => $value) - { - // Clean up the variable just in case - $key = trim(strtolower($key)); - - // Assigns valid keys to the appropriate class property - if (in_array($key, ['fields', 'table', 'conditions', 'group', 'having', 'order', 'limit', 'offset'])) - { - $this->$key = $value; - $conditions = false; - } - } - - // If no valid properties were found, assume it's the conditionals - if ($conditions == true) - { - $this->conditions = $parameters; - } - - return true; - } - - return false; - } - - /** - * Field Values - * - * Pulls the value from a single field and returns an array without any - * duplicates. Perfect for extracting foreign keys to use in later queries. - * - * @param string $field field we want the values for - * @return array values for the passed field - */ - public function fieldvalues($field) - { - $values = []; - - foreach ($this->records as $record) - { - $values[] = $record[$field]; - } - - return array_unique($values); - } - - // }}} + // {{{ Properties + + /** + * Model Name + * + * @var string + */ + public $model = null; + + /** + * Columns + * + * Mapping of key columns for the table. + * + * @var array + */ + public $columns = null; + + /** + * Whether or not to use cache + * + * @var boolean + */ + public $use_cache = false; + + /** + * SQL Array + * + * @var array + */ + public $sql = []; + + /** + * Input Parameters Array + * + * @var array + */ + public $input_parameters = []; + + /** + * Insert Priority + * + * Defaults to false (normal priority) but can be set to "low" or "high" + * + * @var string + */ + public $priority = false; + + /** + * Delayed Insert + * + * @var boolean + */ + public $delayed = false; + + /** + * Ignore Unique Index + * + * @var boolean + */ + public $ignore = false; + + /** + * Replace instead of Insert/Update? + * + * @var boolean + */ + public $replace = false; + + /** + * Field List + * + * SQL: SELECT + * + * @var mixed, string or array + */ + public $fields = '*'; + + /** + * Table Name + * + * SQL: FROM + * + * @var string + */ + public $table = false; + + /** + * Conditions + * + * SQL: WHERE + * + * @var array + */ + public $conditions = false; + + /** + * Group + * + * SQL: GROUP BY + * + * @var mixed, string or array + */ + public $group = false; + + /** + * Having + * + * SQL: HAVING + * + * @var mixed, string or array + */ + public $having = false; + + /** + * Order + * + * SQL: ORDER BY + * + * @var mixed, string or array + */ + public $order = false; + + /** + * Limit + * + * SQL: LIMIT + * + * @var mixed, integer or array + */ + public $limit = false; + + /** + * Offset + * + * SQL: OFFSET + * + * @var integer + */ + public $offset = false; + + /** + * Query Results + * + * @var array + */ + public $results = null; + + /** + * Index + * + * @var integer + */ + public $index = null; + + /** + * Record + * + * @var array + */ + public $record = null; + + /** + * Records + * + * @var array + */ + public $records = null; + + /** + * Original Record + * + * @var array + */ + public $original = null; + + /** + * Iterate + * + * Used to hold the status during a walk() + * + * @var boolean + */ + public $iterate = false; + + /** + * Snapshot + * + * Snapshot of the object properties + * + * @var array + */ + public $snapshot = []; + + /** + * MySQL? + * + * Whether or not we're using MySQL + * + * @var boolean + */ + public $mysql = false; + + /** + * PostgreSQL? + * + * Whether or not we're using PostgreSQL + * + * @var boolean + */ + public $postgresql = false; + + /** + * Commit Type + * + * Indicates what we want to commit. Defaults to a single row commit, any + * calls to queue() will force the commit to process the queue. + * + * @var string + */ + public $commit_type = 'row'; + + // }}} + // {{{ Class Constructor + + /** + * Constructor + * + * Creates a new (empty) object or populates the record set. + * + * @param mixed $type_or_parameters optional type of query or parameters + * @param array $parameters optional data to create a query from + * @param string $passed_key optional key to use for caching + */ + public function __construct($type_or_parameters = null, $parameters = null, $passed_key = null) + { + // Errors if a table is not set. You're welcome, Geoff. + if ($this->table == false) + { + throw new Exception('You must set the table variable'); + } + + // Runs the parent constructor so we have the config + parent::__construct(['cache', 'db']); + + // Interrogates our database object + $this->use_cache = $this->db->cache; + $this->mysql = ($this->db->driver == 'pdo_mysql'); + $this->postgresql = ($this->db->driver == 'pdo_pgsql'); + + // Grabs the class name to use in our cache keys + $this->model = get_class($this); + + // Default column mapping + $columns = [ + 'id' => 'id', + 'created_at' => 'created_at', + 'created_id' => 'created_id', + 'updated_at' => 'updated_at', + 'updated_id' => 'updated_id', + 'deleted_at' => 'deleted_at', + 'deleted_id' => 'deleted_id', + 'is_deleted' => 'is_deleted', + ]; + + // Sets all but the `id` column to false + if ($this->columns === false) + { + foreach ($columns as $column => $field) + { + if ($column != 'id') + { + $columns[$column] = false; + } + } + } + // Merges the model's columns with the defaults + elseif (is_array($this->columns)) + { + foreach ($this->columns as $column => $field) + { + $columns[$column] = $field; + } + } + + $this->columns = $columns; + + // Takes a snapshot of the [non-object] object properties + foreach ($this as $variable => $value) + { + if (!in_array($variable, ['db', 'cache', 'config', 'snapshot'])) + { + $this->snapshot[$variable] = $value; + } + } + + return $this->execute($type_or_parameters, $parameters, $passed_key); + } + + // }}} + // {{{ Database Execution Methods + + /** + * Execute + * + * Potentially populates the record set from the passed arguments. + * + * @param mixed $type_or_parameters optional type of query or parameters + * @param mixed $parameter_or_key optional data to create query or cache key + * @param string $passed_key optional key to use for caching + */ + public function execute($type_or_parameters = null, $parameters_or_key = null, $passed_key = null) + { + // Resets internal properties + foreach ($this->snapshot as $variable => $value) + { + $this->$variable = $value; + } + + // Builds out the query + if ($type_or_parameters != null) + { + // Loads the parameters into the object + if (is_array($type_or_parameters)) + { + if (is_array($parameters_or_key)) + { + throw new Exception('You cannot pass in 2 query parameter arrays'); + } + + $this->prepareParameters($type_or_parameters); + + if ($this->use_cache + && isset($type_or_parameters['conditions'][$this->columns['id']]) + && count($type_or_parameters) == 1 + && count($type_or_parameters['conditions']) == 1) + { + $cache_keys = []; + $sorted_records = []; + + if (!is_array($type_or_parameters['conditions'][$this->columns['id']])) + { + $type_or_parameters['conditions'][$this->columns['id']] = [$type_or_parameters['conditions'][$this->columns['id']]]; + } + + foreach ($type_or_parameters['conditions'][$this->columns['id']] as $id) + { + $cache_keys[] = strtoupper($this->model) . '-' . $id; + $sorted_records[$id] = true; + } + + $cached = $this->cache->get($cache_keys); + $partial_cache = []; + + if ($cached !== false) + { + foreach ($cached as $record) + { + $partial_cache[$record['id']] = $record; + } + } + + unset($cached); + + foreach ($type_or_parameters['conditions'][$this->columns['id']] as $key => $id) + { + if (isset($partial_cache[$id])) + { + unset($type_or_parameters['conditions'][$this->columns['id']][$key]); + } + } + + if (count($type_or_parameters['conditions'][$this->columns['id']]) == 0) + { + $cache_key = true; + $cached = array_values($partial_cache); + } + } + + if ($this->columns['is_deleted']) + { + $type_or_parameters['conditions'][$this->columns['is_deleted']] = '0'; + } + + $this->loadParameters($type_or_parameters); + } + elseif (is_array($parameters_or_key)) + { + $this->prepareParameters($parameters_or_key); + + // @todo Fix cache merging to allow for this + /* + if ($this->use_cache + && isset($parameters_or_key['conditions'][$this->columns['id']]) + && count($parameters_or_key) == 1 + && count($parameters_or_key['conditions']) == 1) + { + $cache_keys = []; + $sorted_records = []; + + foreach ($parameters_or_key['conditions'][$this->columns['id']] as $id) + { + $cache_keys[] = strtoupper($this->model) . '-' . $id; + $sorted_records[$id] = true; + } + + $cached = $this->cache->get($cache_keys); + $partial_cache = []; + + if ($cached !== false) + { + foreach ($cached as $record) + { + $partial_cache[$record['id']] = $record; + } + } + + unset($cached); + + foreach ($parameters_or_key['conditions'][$this->columns['id']] as $key => $id) + { + if (isset($partial_cache[$id])) + { + unset($parameters_or_key['conditions'][$this->columns['id']][$key]); + } + } + + if (count($parameters_or_key['conditions'][$this->columns['id']]) == 0) + { + $cache_key = true; + $cached = array_values($partial_cache); + } + } + */ + + if ($this->columns['is_deleted']) + { + $parameters_or_key['conditions'][$this->columns['is_deleted']] = '0'; + } + + $this->loadParameters($parameters_or_key); + } + elseif (ctype_digit((string)$type_or_parameters)) + { + $cache_key = strtoupper($this->model) . '-' . $type_or_parameters; + $parameters_or_key = [$this->columns['id'] => $type_or_parameters]; + + if ($this->columns['is_deleted']) + { + $parameters_or_key[$this->columns['is_deleted']] = '0'; + } + + $this->loadParameters($parameters_or_key); + } + elseif (ctype_digit((string)$parameters_or_key)) + { + // @todo Fix cache merging to allow for this + //$cache_key = strtoupper($this->model) . '-' . $parameters_or_key; + + $parameters_or_key = [$this->columns['id'] => $parameters_or_key]; + + if ($this->columns['is_deleted']) + { + $parameters_or_key[$this->columns['is_deleted']] = '0'; + } + + $this->loadParameters($parameters_or_key); + } + elseif ($this->columns['is_deleted']) + { + $this->loadParameters([$this->columns['is_deleted'] => '0']); + } + + if (is_string($passed_key)) + { + $cache_key = $passed_key; + } + + // Starts with a basic SELECT ... FROM + $this->sql = [ + 'SELECT ' . (is_array($this->fields) ? implode(', ', $this->fields) : $this->fields), + 'FROM ' . $this->table, + ]; + + // Updates query to use COUNT syntax + if ($type_or_parameters == 'count') + { + $this->sql[0] = 'SELECT COUNT(*) AS count'; + $this->generateQuery(); + } + // Adds the rest of the query + elseif (!isset($cache_key) || $cache_key !== true) + { + $this->generateQuery(); + } + + if (isset($cache_key) && $this->use_cache && !isset($cached)) + { + $cached = $this->cache->get($cache_key); + } + + if (isset($cached) && $cached !== false) + { + $this->records = $cached; + } + else + { + $this->records = $this->db->fetch( + implode(' ', $this->sql), + (count($this->input_parameters) == 0 ? null : $this->input_parameters) + ); + + if (isset($partial_cache) && count($this->records)) + { + $records = array_merge($partial_cache, $this->records); + + if (isset($sorted_records)) + { + foreach ($records as $record) + { + $sorted_records[$record['id']] = $record; + } + + $records = $sorted_records; + } + + $this->records = $records; + } + + if ($this->use_cache) + { + if (isset($cache_key)) + { + if ($passed_key) + { + $cache_value = $this->records; + } + elseif (isset($this->records[0])) + { + $cache_value = $this->records[0]; + } + + // Only set the value for non-empty records. Caching + // values that are empty could be caused by querying + // records that don't exist at the moment, but could + // exist in the future. INSERTs do not do any sort of + // cache invalidation at this time. + if (isset($cache_value)) + { + $this->cache->set($cache_key, $cache_value); + } + } + elseif (isset($cache_keys)) + { + // @todo Move to Memcached extension and switch to use setMulti() + foreach ($this->records as $record) + { + if (isset($record['id'])) + { + $this->cache->set(strtoupper($this->model) . '-' . $record['id'], $record); + } + } + } + } + } + + $index_records = in_array($type_or_parameters, ['list', 'indexed']); + + // Flattens the data into a list + if ($index_records == true) + { + $list = []; + + foreach ($this->records as $record) + { + // Uses the first value as the key and the second as the value + if ($type_or_parameters == 'list') + { + $list[array_shift($record)] = array_shift($record); + } + // Uses the first value as the key + else + { + $list[current($record)] = $record; + } + } + + $this->records = $list; + } + + // Sets up the current record + if (isset($this->records[0])) + { + $this->record = $this->records[0]; + } + else + { + if ($index_records == true) + { + $this->record[key($this->records)] = current($this->records); + } + else + { + $this->record = $this->records; + } + } + + if (!preg_match('/^[0-9]+$/', implode('', array_keys($this->records)))) + { + $this->records = [$this->records]; + } + + $this->index = 0; + $this->original = $this->records; + } + + return true; + } + + // }}} + // {{{ SQL Generation Methods + + /** + * Generate Query + * + * Goes through all of the object variables that correspond with parts of + * the query and adds them to the master SQL array. + * + * @return array $this->sql an array of SQL parts + */ + public function generateQuery() + { + // Adds the WHERE conditionals + if ($this->conditions != false) + { + $use_id = true; + + foreach ($this->conditions as $column => $value) + { + if (!is_int($column)) + { + $use_id = false; + } + } + + if ($use_id) + { + $this->conditions = [$this->columns['id'] => $this->conditions]; + } + + $this->sql[] = 'WHERE ' . (is_array($this->conditions) ? $this->generateConditions($this->conditions) : $this->conditions); + } + + // Adds the GROUP BY syntax + if ($this->group != false) + { + $this->sql[] = 'GROUP BY ' . (is_array($this->group) ? implode(', ', $this->group) : $this->group); + } + + // Adds the HAVING conditions + if ($this->having != false) + { + $this->sql[] = 'HAVING ' . (is_array($this->having) ? $this->generateConditions($this->having) : $this->having); + } + + // Adds the ORDER BY syntax + if ($this->order != false) + { + $this->sql[] = 'ORDER BY ' . (is_array($this->order) ? implode(', ', $this->order) : $this->order); + } + + // Adds the LIMIT syntax + if ($this->limit != false) + { + $this->sql[] = 'LIMIT ' . (is_array($this->limit) ? implode(', ', $this->limit) : $this->limit); + } + + // Adds the OFFSET syntax + if ($this->offset != false) + { + $this->sql[] = 'OFFSET ' . $this->offset; + } + + return $this->sql; + } + + /** + * Generate Conditions + * + * Generates the conditional blocks of SQL from the passed array of + * conditions. Supports as much as I could remember to implement. This + * method is utilized by both the WHERE and HAVING clauses. + * + * @param array $conditions array of potentially nested conditions + * @param boolean $inject_values whether or not to use input parameters + * @param string $conditional syntax to use between conditions + * @return string $sql generated SQL for the conditions + */ + public function generateConditions($conditions, $inject_values = false, $conditional = 'AND') + { + $sql = ''; + + foreach ($conditions as $key => $value) + { + $key = trim($key); + + if ($sql != '') + { + if (preg_match('/^(AND|&&|OR|\|\||XOR)( NOT)?/i', $key)) + { + $sql .= ' '; + } + else + { + $sql .= ' ' . $conditional . ' '; + } + } + + // Checks for our keywords to control the flow + $operator = preg_match('/(<|<=|=|>=|>|!=|!|<>| LIKE)$/i', $key); + $between = preg_match('/ BETWEEN$/i', $key); + $is_is_not = preg_match('/( IS| IS NOT)$/i', $key); + + // Checks for boolean and null + $is_true = ($value === true); + $is_false = ($value === false); + $is_null = ($value === null); + + // Generates an in statement + if (is_array($value) && $between == false) + { + $sql .= $key . ' in ('; + + if ($inject_values == true) + { + $sql .= implode(', ', $value); + } + else + { + $sql .= implode(', ', array_fill(1, count($value), '?')); + $this->input_parameters = array_merge($this->input_parameters, $value); + } + + $sql .= ')'; + } + else + { + // If the key is numeric it wasn't set, so don't use it + if (is_numeric($key)) + { + $sql .= $value; + } + else + { + // Omits the operator as the operator is there + if ($operator == true || $is_is_not == true) + { + if ($is_true || $is_false || $is_null) + { + // Scrubs the operator if someone doesn't use IS / IS NOT + if ($operator == true) + { + $key = preg_replace('/ ?(!=|!|<>)$/i', ' IS NOT', $key); + $key = preg_replace('/ ?(<|<=|=|>=| LIKE)$/i', ' IS', $key); + } + + $sql .= $key . ' '; + + if ($is_true) + { + $sql .= 'TRUE'; + } + elseif ($is_false) + { + $sql .= 'FALSE'; + } + else + { + $sql .= 'NULL'; + } + } + else + { + $sql .= $key . ' '; + + if ($inject_values == true) + { + $sql .= $value; + } + else + { + $sql .= '?'; + $this->input_parameters[] = $value; + } + } + } + // Generates a between statement + elseif ($between == true) + { + if (is_array($value)) + { + // Checks the number of values, between expects 2 + if (count($value) != 2) + { + throw new Exception('BETWEEN expects an array with 2 values.'); + } + else + { + $sql .= $key . ' '; + + if ($inject_values == true) + { + $sql .= $value[0] . ' AND ' . $value[1]; + } + else + { + $sql .= '? AND ?'; + $this->input_parameters = array_merge($this->input_parameters, $value); + } + } + } + else + { + throw new Exception('BETWEEN expects an array.'); + } + } + else + { + $sql .= $key . ' '; + + // Checks if we're working with constants + if ($is_true) + { + $sql .= 'IS TRUE'; + } + elseif ($is_false) + { + $sql .= 'IS FALSE'; + } + elseif ($is_null) + { + $sql .= 'IS NULL'; + } + else + { + if ($inject_values == true) + { + $sql .= '= ' . $value; + } + else + { + $sql .= '= ?'; + $this->input_parameters[] = $value; + } + } + } + } + } + } + + return $sql; + } + + // }}} + // {{{ Record Interaction Methods + + /** + * Count Records + * + * Counts the records + */ + public function count() + { + if (isset($this->records[0]) && $this->records[0] == []) + { + return 0; + } + else + { + return count($this->records); + } + } + + /** + * Sort Records + * + * Sorts the records by the specified index in the specified order. + * + * @param string $index the index to be sorted on + * @param string $order the direction to order + * @return boolean true + * @todo Implement this method + */ + public function sort($index, $order = 'asc') + { + return true; + } + + /** + * Shuffle Records + * + * Sorts the records in a pseudo-random order. + * + * @return boolean true + * @todo Implement this method + */ + public function shuffle() + { + return true; + } + + /** + * Next Record + * + * Increment the record array to the next member of the record set. + * + * @return boolean whether or not there was next element + */ + public function next() + { + $return = (boolean)($this->record = next($this->records)); + + if ($return == true) + { + $this->index++; + } + + return $return; + } + + /** + * Previous Record + * + * Decrement the record array to the next member of the record set. + * + * @return boolean whether or not there was previous element + */ + public function prev() + { + $return = (boolean)($this->record = prev($this->records)); + + if ($return == true) + { + $this->index--; + } + + return $return; + } + + /** + * Reset Record + * + * Set the pointer to the first element of the record set. + * + * @return boolean whether or not records is an array (and could be reset) + */ + public function reset() + { + $return = (boolean)($this->record = reset($this->records)); + + if ($return == true) + { + $this->index = 0; + } + + return $return; + } + + /** + * First Record + * + * Alias of reset(). "first" is more intuitive to me, but reset stays in + * line with the built in PHP functions. Not sure why I'd want to add some + * consistency to one of the most inconsistent languages. + * + * @return boolean whether or not records is an array (and could be reset) + */ + public function first() + { + return $this->reset(); + } + + /** + * End Record + * + * Set the pointer to the last element of the record set. + * + * @return boolean whether or not records is an array (and end() worked) + */ + public function end() + { + $return = (boolean)($this->record = end($this->records)); + + if ($return == true) + { + $this->index = $this->count() - 1; + } + + return $return; + } + + /** + * Last record + * + * Alias of end(). "last" is more intuitive to me, but end stays in line + * with the built in PHP functions. + * + * @return boolean whether or not records is an array (and end() worked) + */ + public function last() + { + return $this->end(); + } + + /** + * Walk Records + * + * Returns the current record and advances to the next. Built to allow for + * simplified code when looping through a record set. + * + * @return mixed either an array of the current record or false + * @todo does not currently support "indexed" or "list" return types + */ + public function walk() + { + // checks if we should start iterating, solves off by one issues with next() + if ($this->iterate == false) + { + $this->iterate = true; + + // resets the records, saves calling reset() when walking multiple times + $this->reset(); + } + else + { + $this->next(); + } + + return $this->record; + } + + /** + * Queue Record + * + * Stashes the current record and creates an empty record ready to be + * manipulated. Eliminates looping through records and inserting each one + * separately and/or the need for helper methods in the models. + */ + public function queue() + { + $this->commit_type = 'queue'; + $this->records[] = $this->record; + $this->record = null; + } + + // }}} + // {{{ Record Manipulation Methods + + /** + * Commit + * + * INSERTs or UPDATEs a record in the database. + * + * @return boolean results of the query + */ + public function commit() + { + // Multiple row query / queries + if ($this->commit_type == 'queue') + { + $update = false; + $cache_keys = []; + + /** + * @todo I outta loop through twice to determine if it's an INSERT + * or an UPDATE. As it stands, you could run into a scenario + * where you could have a mixed lot that would attempt to + * build out a query with both INSERT and UPDATE syntax and + * would probably cause a doomsday scenario for our universe. + * @todo Doesn't play nice with ->walk() at all. Ends up stuck in + * an infinite loop and never executes. Could be part of the + * aforementioned doomsday scenario and fortunately PHP isn't + * letting it happen thanks to memory constraints. + */ + foreach ($this->records as $record) + { + // Performs an UPDATE with multiple queries + if (array_key_exists($this->columns['id'], $record)) + { + $update = true; + + if (!isset($sql)) + { + $sql = ''; + $input_parameters = []; + } + + $update_fields = []; + + foreach ($record as $field => $value) + { + if ($field != $this->columns['id']) + { + $update_fields[] = $field . ' = ?'; + $input_parameters[] = (is_array($value) ? json_encode($value) : $value); + } + else + { + $cache_keys[] = strtoupper($this->model) . '-' . $value; + } + } + + // @todo Check if the column was passed in + if ($this->columns['updated_at'] != false) + { + $update_fields[] = $this->columns['updated_at'] . ' = ?'; + $input_parameters[] = Time::timestamp(); + } + + // @todo Check if the column was passed in + if ($this->columns['updated_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) + { + $update_fields[] = $this->columns['updated_id'] . ' = ?'; + $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; + } + + if ($sql != '') + { + $sql .= '; '; + } + + $sql .= 'UPDATE ' . $this->table + . ' SET ' . implode(', ', $update_fields) + . ' WHERE ' . $this->columns['id'] . ' = ?'; + + $input_parameters[] = $record[$this->columns['id']]; + } + // Performs a multiple row INSERT + else + { + if (!isset($sql)) + { + $field_count = count($record); + $insert_fields = array_keys($record); + + if ($this->columns['created_at'] != false) + { + $insert_fields[] = $this->columns['created_at']; + $field_count++; + } + + if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) + { + $insert_fields[] = $this->columns['created_id']; + $field_count++; + } + + $values = '(' . implode(', ', array_fill(0, $field_count, '?')) . ')'; + $input_parameters = []; + + // INSERT INTO ... + $sql = 'INSERT INTO ' . $this->table . ' (' . implode(', ', $insert_fields) . ') VALUES ' . $values; + } + else + { + $sql .= ', ' . $values; + } + + foreach ($record as $variable => $value) + { + $input_parameters[] = (is_array($value) ? json_encode($value) : $value); + } + + // @todo Check if the column was passed in + if ($this->columns['created_at'] != false) + { + $input_parameters[] = Time::timestamp(); + } + + // @todo Check if the column was passed in + if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) + { + $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; + } + } + } + + $results = $this->db->execute($sql . ';', $input_parameters); + + // Clears the cache + if ($update && $this->use_cache) + { + $this->cache->delete($cache_keys); + } + + return $results; + } + // Single row INSERT or UPDATE + else + { + // Determines if it's an UPDATE or INSERT + $update = (isset($this->record[$this->columns['id']]) && trim($this->record[$this->columns['id']]) != ''); + + // Starts to build the query, optionally sets PRIORITY, DELAYED and IGNORE syntax + if ($this->replace === true && $this->mysql) + { + $sql = 'REPLACE'; + + if (strtoupper($this->priority) == 'LOW') + { + $sql .= ' LOW_PRIORITY'; + } + elseif ($this->delayed == true) + { + $sql .= ' DELAYED'; + } + + $sql .= ' INTO ' . $this->table; + } + else + { + if ($update == true) + { + $sql = 'UPDATE'; + } + else + { + $sql = 'INSERT'; + + // priority syntax takes priority over delayed + if ($this->mysql) + { + if ($this->priority !== false + && in_array(strtoupper($this->priority), ['LOW', 'HIGH'])) + { + $sql .= ' ' . strtoupper($this->priority) . '_PRIORITY'; + } + elseif ($this->delayed == true) + { + $sql .= ' DELAYED'; + } + + if ($this->ignore == true) + { + $sql .= ' IGNORE'; + } + } + + $sql .= ' INTO'; + } + + $sql .= ' ' . $this->table . ($update ? ' SET ' : ' '); + } + + $input_parameters = null; + + // Limits the columns being updated + $record = ($update ? array_diff_assoc( + $this->record, + isset($this->original[$this->index]) ? $this->original[$this->index] : [] + ) : $this->record); + + // Makes sure there's something to INSERT or UPDATE + if (count($record) > 0) + { + if ($this->replace && $update) + { + $update = false; + } + + $insert_fields = []; + + // Loops through all the columns and assembles the query + foreach ($record as $column => $value) + { + if ($column != $this->columns['id']) + { + if ($update == true) + { + if ($input_parameters != null) + { + $sql .= ', '; + } + + $sql .= $column . ' = '; + + if (in_array($value, ['++', '--'])) + { + $sql .= $column . ' ' . substr($value, 0, 1) . ' ?'; + $value = 1; + } + else + { + $sql .= '?'; + } + } + else + { + $insert_fields[] = $column; + } + + $input_parameters[] = (is_array($value) ? json_encode($value) : $value); + } + } + + // If it's an UPDATE tack on the ID + if ($update == true) + { + if ($this->columns['updated_at'] != false) + { + if ($input_parameters != null) + { + $sql .= ', '; + } + + $sql .= $this->columns['updated_at'] . ' = ?'; + $input_parameters[] = Time::timestamp(); + } + + if ($this->columns['updated_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) + { + if ($input_parameters != null) + { + $sql .= ', '; + } + + $sql .= $this->columns['updated_id'] . ' = ?'; + + $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; + } + + $sql .= ' WHERE ' . $this->columns['id'] . ' = ?' . ($this->mysql ? ' LIMIT 1' : '') . ';'; + $input_parameters[] = $this->record[$this->columns['id']]; + } + else + { + // @todo REPLACE should be grabbing the previous values so + // that we're not wiping out pertinent data when the + // internal columns are in use. This includes the + // `id` column that is needed to keep it from doing + // an INSERT instead of an UPDATE + if ($this->columns['created_at'] != false || $this->replace) + { + $insert_fields[] = $this->columns['created_at']; + $input_parameters[] = Time::timestamp(); + } + + if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id'])) + { + $insert_fields[] = $this->columns['created_id']; + $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; + } + + $sql .= '(' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', array_fill(0, count($input_parameters), '?')) . ')'; + + // PDO::lastInsertID() doesn't work so we return the ID with the query + if ($this->postgresql) + { + $sql .= ' RETURNING ' . $this->columns['id']; + } + + $sql .= ';'; + } + + // Executes the query + if ($this->postgresql && $update == false) + { + return $this->db->fetch($sql, $input_parameters); + } + else + { + $results = $this->db->execute($sql, $input_parameters); + + // Clears the cache + if ($update && $this->use_cache) + { + $this->cache->delete(strtoupper($this->model) . '-' . $this->record[$this->columns['id']]); + } + + return $results; + } + } + } + + return false; + } + + /** + * Delete Record + * + * DELETEs the current record from the database. + * + * @return boolean status of the query + */ + public function delete() + { + if (isset($this->record[$this->columns['id']])) + { + // Logical deletion + if ($this->columns['is_deleted']) + { + $sql = 'UPDATE ' . $this->table . ' SET ' . $this->columns['is_deleted'] . ' = ?'; + $input_parameters = ['1']; + + if ($this->columns['deleted_at']) + { + $sql .= ', ' . $this->columns['deleted_at'] . ' = ?'; + $input_parameters[] = Time::timestamp(); + } + + if ($this->columns['deleted_id'] && isset($_SESSION['__pickles']['security']['user_id'])) + { + $sql .= ', ' . $this->columns['deleted_id'] . ' = ?'; + $input_parameters[] = $_SESSION['__pickles']['security']['user_id']; + } + + $sql .= ' WHERE ' . $this->columns['id'] . ' = ?'; + } + // For reals deletion + else + { + $sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->columns['id'] . ' = ?' . ($this->mysql ? ' LIMIT 1' : '') . ';'; + } + + $input_parameters[] = $this->record[$this->columns['id']]; + $results = $this->db->execute($sql, $input_parameters); + + // Clears the cache + if ($this->use_cache) + { + $this->cache->delete(strtoupper($this->model) . '-' . $this->record[$this->columns['id']]); + } + + return $results; + } + else + { + return false; + } + } + + // }}} + // {{{ Utility Methods + + /** + * Prepare Parameters + * + * Checks if the parameters array is only integers and reconstructs the + * array with the proper conditions format. + * + * @param array $array parameters array, passed by reference + */ + public function prepareParameters(&$parameters) + { + $all_integers = true; + + foreach ($parameters as $key => $value) + { + if (!ctype_digit((string)$key) || !ctype_digit((string)$value)) + { + $all_integers = false; + } + } + + if ($all_integers) + { + $parameters = ['conditions' => [$this->columns['id'] => $parameters]]; + } + } + + /** + * Load Parameters + * + * Loads the passed parameters back into the object. + * + * @param array $parameters key / value list + * @param boolean whether or not the parameters were loaded + */ + public function loadParameters($parameters) + { + if (is_array($parameters)) + { + $conditions = true; + + // Adds the parameters to the object + foreach ($parameters as $key => $value) + { + // Clean up the variable just in case + $key = trim(strtolower($key)); + + // Assigns valid keys to the appropriate class property + if (in_array($key, ['fields', 'table', 'conditions', 'group', 'having', 'order', 'limit', 'offset'])) + { + $this->$key = $value; + $conditions = false; + } + } + + // If no valid properties were found, assume it's the conditionals + if ($conditions == true) + { + $this->conditions = $parameters; + } + + return true; + } + + return false; + } + + /** + * Field Values + * + * Pulls the value from a single field and returns an array without any + * duplicates. Perfect for extracting foreign keys to use in later queries. + * + * @param string $field field we want the values for + * @return array values for the passed field + */ + public function fieldvalues($field) + { + $values = []; + + foreach ($this->records as $record) + { + $values[] = $record[$field]; + } + + return array_unique($values); + } + + // }}} } -?> diff --git a/src/classes/Module.php b/src/classes/Module.php index 9ed9205..44c9a26 100644 --- a/src/classes/Module.php +++ b/src/classes/Module.php @@ -27,268 +27,267 @@ */ class Module extends Object { - /** - * Page Title - * - * @var string, null by default - * @todo Abandon for $this->meta - */ - public $title = null; + /** + * Page Title + * + * @var string, null by default + * @todo Abandon for $this->meta + */ + public $title = null; - /** - * Meta Description - * - * @var string, null by default - * @todo Abandon for $this->meta - */ - public $description = null; + /** + * Meta Description + * + * @var string, null by default + * @todo Abandon for $this->meta + */ + public $description = null; - /** - * Meta Keywords (comma separated) - * - * @var string, null by default - * @todo Abandon for $this->meta - */ - public $keywords = null; + /** + * Meta Keywords (comma separated) + * + * @var string, null by default + * @todo Abandon for $this->meta + */ + public $keywords = null; - /** - * Meta Data - * - * @var array - */ - public $meta = [ - 'title' => '', - 'description' => '', - 'keywords' => '', - ]; + /** + * Meta Data + * + * @var array + */ + public $meta = [ + 'title' => '', + 'description' => '', + 'keywords' => '', + ]; - /** - * Secure - * - * Whether or not the page should be loaded via SSL. - * - * @var boolean defaults to false - */ - public $secure = false; + /** + * Secure + * + * Whether or not the page should be loaded via SSL. + * + * @var boolean defaults to false + */ + public $secure = false; - /** - * Security Settings - * - * @var boolean, null by default - */ - public $security = null; + /** + * Security Settings + * + * @var boolean, null by default + */ + public $security = null; - /** - * AJAX - * - * Whether or not the module is being called via AJAX. This determines if - * errors should be returned as JSON or if it should use the Error class - * which can be interrogated from within a template. - * - * @var boolean, false (not AJAX) by default - * @todo Doesn't seem to be in use, but I have it defined on Clipinary - * don't want to remove until I drop it else it would end up in the - * module return array. - */ - public $ajax = false; + /** + * AJAX + * + * Whether or not the module is being called via AJAX. This determines if + * errors should be returned as JSON or if it should use the Error class + * which can be interrogated from within a template. + * + * @var boolean, false (not AJAX) by default + * @todo Doesn't seem to be in use, but I have it defined on Clipinary + * don't want to remove until I drop it else it would end up in the + * module return array. + */ + public $ajax = false; - /** - * Method - * - * Request methods that are allowed to access the module. - * - * @var string or array, null by default - */ - public $method = null; + /** + * Method + * + * Request methods that are allowed to access the module. + * + * @var string or array, null by default + */ + public $method = null; - /** - * Validate - * - * Variables to validate. - * - * @var array - */ - public $validate = []; + /** + * Validate + * + * Variables to validate. + * + * @var array + */ + public $validate = []; - /** - * Template - * - * This is the parent template that will be loaded if you are using the - * 'template' return type in the Display class. Parent templates are found - * in ./templates/__shared and use the phtml extension. - * - * @var string, 'index' by default - */ - public $template = 'index'; + /** + * Template + * + * This is the parent template that will be loaded if you are using the + * 'template' return type in the Display class. Parent templates are found + * in ./templates/__shared and use the phtml extension. + * + * @var string, 'index' by default + */ + public $template = 'index'; - /** - * Return - * - * Array that is returned to the template in the case of the module not - * returning anything itself. This is somewhat of a one way trip as you - * cannot get the variable unless you reference the return array explicitly - * $this->return['variable'] - * - * @var array - * @todo Rename __return so it's kinda obscured - * @todo Will need to update leaderbin and sndcrd to use new variable - */ - public $return = []; + /** + * Return + * + * Array that is returned to the template in the case of the module not + * returning anything itself. This is somewhat of a one way trip as you + * cannot get the variable unless you reference the return array explicitly + * $this->return['variable'] + * + * @var array + * @todo Rename __return so it's kinda obscured + * @todo Will need to update leaderbin and sndcrd to use new variable + */ + public $return = []; - /** - * Output - * - * What should the class render as output? This can be a string or an array - * containing either 'json', 'rss', 'template' or 'xml'. Default is to use - * templates and if the template is not present, fall back to JSON. - * - * @var mixed string or array - */ - public $output = ['template', 'json']; + /** + * Output + * + * What should the class render as output? This can be a string or an array + * containing either 'json', 'rss', 'template' or 'xml'. Default is to use + * templates and if the template is not present, fall back to JSON. + * + * @var mixed string or array + */ + public $output = ['template', 'json']; - /** - * Constructor - * - * The constructor does nothing by default but can be passed a boolean - * variable to tell it to automatically run the __default() method. This is - * typically used when a module is called outside of the scope of the - * controller (the registration page calls the login page in this manner. - * - * @param boolean $autorun optional flag to autorun __default() - * @param boolean $valiate optional flag to disable autorun validation - */ - public function __construct($autorun = false, $validate = true) - { - parent::__construct(['cache', 'db']); + /** + * Constructor + * + * The constructor does nothing by default but can be passed a boolean + * variable to tell it to automatically run the __default() method. This is + * typically used when a module is called outside of the scope of the + * controller (the registration page calls the login page in this manner. + * + * @param boolean $autorun optional flag to autorun __default() + * @param boolean $valiate optional flag to disable autorun validation + */ + public function __construct($autorun = false, $validate = true) + { + parent::__construct(['cache', 'db']); - if ($autorun === true) - { - if ($validate === true) - { - $errors = $this->__validate(); + if ($autorun === true) + { + if ($validate === true) + { + $errors = $this->__validate(); - if ($errors !== false) - { - // @todo Fatal error perhaps? - exit('Errors encountered, this is a @todo for form validation when calling modules from inside of modules'); - } - } + if ($errors !== false) + { + // @todo Fatal error perhaps? + exit('Errors encountered, this is a @todo for form validation when calling modules from inside of modules'); + } + } - $this->__default(); - } - } + $this->__default(); + } + } - /** - * Default "Magic" Method - * - * This function is overloaded by the module. The __default() method is - * where you want to place any code that needs to be executed at runtime. - */ - public function __default() - { + /** + * Default "Magic" Method + * + * This function is overloaded by the module. The __default() method is + * where you want to place any code that needs to be executed at runtime. + */ + public function __default() + { - } + } - /** - * Magic Setter Method - * - * Places undefined properties into the return array as part of the - * module's payload. - * - * @param string $name name of the variable to be set - * @param mixed $value value of the variable to be set - */ - public function __set($name, $value) - { - $this->return[$name] = $value; - } + /** + * Magic Setter Method + * + * Places undefined properties into the return array as part of the + * module's payload. + * + * @param string $name name of the variable to be set + * @param mixed $value value of the variable to be set + */ + public function __set($name, $value) + { + $this->return[$name] = $value; + } - /** - * Magic Getter Method - * - * Any variables not defined in this class are set in the return array and - * default to false if not defined there. - * - * @param string $name name of the variable requested - * @return mixed value of the variable or boolean false - */ - public function __get($name) - { - if (!isset($this->return[$name])) - { - return false; - } - else - { - return $this->return[$name]; - } - } + /** + * Magic Getter Method + * + * Any variables not defined in this class are set in the return array and + * default to false if not defined there. + * + * @param string $name name of the variable requested + * @return mixed value of the variable or boolean false + */ + public function __get($name) + { + if (!isset($this->return[$name])) + { + return false; + } + else + { + return $this->return[$name]; + } + } - /** - * Validate - * - * Internal validation for data passed to a Module. Grabs the super global - * based on the Module's request method and loops through the data using the - * Module's validation array (if present) sanity checking each variable - * against the rules. - * - * @return mixed boolean false if everything is fine or an array or errors - */ - public function __validate() - { - $errors = []; + /** + * Validate + * + * Internal validation for data passed to a Module. Grabs the super global + * based on the Module's request method and loops through the data using the + * Module's validation array (if present) sanity checking each variable + * against the rules. + * + * @return mixed boolean false if everything is fine or an array or errors + */ + public function __validate() + { + $errors = []; - if ($this->validate) - { - if (is_array($this->method)) - { - $this->method = $this->method[0]; - } + if ($this->validate) + { + if (is_array($this->method)) + { + $this->method = $this->method[0]; + } - switch (strtoupper($this->method)) - { - case 'GET': - $global = &$_GET; - break; + switch (strtoupper($this->method)) + { + case 'GET': + $global = &$_GET; + break; - case 'POST': - $global = &$_POST; - break; + case 'POST': + $global = &$_POST; + break; - default: - $global = &$_REQUEST; - break; - } + default: + $global = &$_REQUEST; + break; + } - foreach ($this->validate as $variable => $rules) - { - if (!is_array($rules) && $rules !== true) - { - $variable = $rules; - $rules = true; - } + foreach ($this->validate as $variable => $rules) + { + if (!is_array($rules) && $rules !== true) + { + $variable = $rules; + $rules = true; + } - if (isset($global[$variable]) && !String::isEmpty($global[$variable])) - { - if (is_array($rules)) - { - $rule_errors = Validate::isValid($global[$variable], $rules); + if (isset($global[$variable]) && !String::isEmpty($global[$variable])) + { + if (is_array($rules)) + { + $rule_errors = Validate::isValid($global[$variable], $rules); - if (is_array($rule_errors)) - { - $errors = array_merge($errors, $rule_errors); - } - } - } - else - { - $errors[] = 'The ' . $variable . ' field is required.'; - } - } - } + if (is_array($rule_errors)) + { + $errors = array_merge($errors, $rule_errors); + } + } + } + else + { + $errors[] = 'The ' . $variable . ' field is required.'; + } + } + } - return $errors == [] ? false : $errors; - } + return $errors == [] ? false : $errors; + } } -?> diff --git a/src/classes/Number.php b/src/classes/Number.php index b2572fc..698bd84 100644 --- a/src/classes/Number.php +++ b/src/classes/Number.php @@ -23,49 +23,48 @@ */ class Number { - /** - * Ordinal Indiciator - * - * Formats a number by appending an ordinal indicator. - * - * @static - * @link http://en.wikipedia.org/wiki/Ordinal_indicator - * @link http://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers - * @param string $number number to format - * @param boolean $superscript include tags - * @return string formatted number - */ - public static function ordinalIndicator($number, $superscript = false) - { - if (!in_array(($number % 100), [11, 12, 13])) - { - switch ($number % 10) - { - case 1: - $suffix = 'st'; - break; + /** + * Ordinal Indiciator + * + * Formats a number by appending an ordinal indicator. + * + * @static + * @link http://en.wikipedia.org/wiki/Ordinal_indicator + * @link http://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers + * @param string $number number to format + * @param boolean $superscript include tags + * @return string formatted number + */ + public static function ordinalIndicator($number, $superscript = false) + { + if (!in_array(($number % 100), [11, 12, 13])) + { + switch ($number % 10) + { + case 1: + $suffix = 'st'; + break; - case 2: - $suffix = 'nd'; - break; + case 2: + $suffix = 'nd'; + break; - case 3: - $suffix = 'rd'; - break; + case 3: + $suffix = 'rd'; + break; - default: - $suffix = 'th'; - break; - } - } + default: + $suffix = 'th'; + break; + } + } - if ($superscript) - { - $suffix = '' . $suffix . ''; - } + if ($superscript) + { + $suffix = '' . $suffix . ''; + } - return $number . $suffix; - } + return $number . $suffix; + } } -?> diff --git a/src/classes/Object.php b/src/classes/Object.php index a04f560..4847d45 100644 --- a/src/classes/Object.php +++ b/src/classes/Object.php @@ -24,127 +24,126 @@ */ class Object { - /** - * Object Instances - * - * @static - * @var array - */ - public static $instances = []; + /** + * Object Instances + * + * @static + * @var array + */ + public static $instances = []; - /** - * Instance of the Config object - * - * @var object - */ - public $config = null; + /** + * Instance of the Config object + * + * @var object + */ + public $config = null; - /** - * Instance of the Cache object - * - * @var object - */ - public $cache = null; + /** + * Instance of the Cache object + * + * @var object + */ + public $cache = null; - /** - * Instance of the Database object - * - * @var object - */ - public $db = null; + /** + * Instance of the Database object + * + * @var object + */ + public $db = null; - /** - * Profiler flag - * - * @var mixed - */ - public $profiler = false; + /** + * Profiler flag + * + * @var mixed + */ + public $profiler = false; - /** - * Constructor - * - * Establishes a Config instance for all children to enjoy - */ - public function __construct($objects = null) - { - // Gets an instance of the config, unless we ARE the config - if (get_class($this) == 'Config') - { - $this->config = true; - } - else - { - $this->config = Config::getInstance(); - } + /** + * Constructor + * + * Establishes a Config instance for all children to enjoy + */ + public function __construct($objects = null) + { + // Gets an instance of the config, unless we ARE the config + if (get_class($this) == 'Config') + { + $this->config = true; + } + else + { + $this->config = Config::getInstance(); + } - if ($objects) - { - if (!is_array($objects)) - { - $objects = [$objects]; - } + if ($objects) + { + if (!is_array($objects)) + { + $objects = [$objects]; + } - foreach ($objects as $object) - { - switch ($object) - { - case 'cache': $this->cache = Cache::getInstance(); break; - case 'db': $this->db = Database::getInstance(); break; - } - } - } + foreach ($objects as $object) + { + switch ($object) + { + case 'cache': $this->cache = Cache::getInstance(); break; + case 'db': $this->db = Database::getInstance(); break; + } + } + } - // Assigns the profiler flag - $this->profiler = (isset($this->config->pickles['profiler']) && $this->config->pickles['profiler'] != '' ? $this->config->pickles['profiler'] : false); + // Assigns the profiler flag + $this->profiler = (isset($this->config->pickles['profiler']) && $this->config->pickles['profiler'] != '' ? $this->config->pickles['profiler'] : false); - // Optionally logs the constructor to the profiler - if ($this->profiler === true || ((is_array($this->profiler) && in_array('objects', $this->profiler)) || stripos($this->profiler, 'objects') !== false)) - { - Profiler::log($this, '__construct'); - } - } + // Optionally logs the constructor to the profiler + if ($this->profiler === true || ((is_array($this->profiler) && in_array('objects', $this->profiler)) || stripos($this->profiler, 'objects') !== false)) + { + Profiler::log($this, '__construct'); + } + } - /** - * Get Instance - * - * Gets an instance of the passed class. Allows for easy sharing of certain - * classes within the system to avoid the extra overhead of creating new - * objects each time. Also avoids the hassle of passing around variables. - * - * @static - * @param string $class name of the class - * @return object instance of the class - */ - public static function getInstance($class = false) - { - // In < 5.3 arguments must match in child, hence defaulting $class - // @todo Remove this, as we're no longer supporting 5.3 - if ($class == false) - { - return false; - } - else - { - if (!isset(self::$instances[$class])) - { - self::$instances[$class] = new $class(); - } + /** + * Get Instance + * + * Gets an instance of the passed class. Allows for easy sharing of certain + * classes within the system to avoid the extra overhead of creating new + * objects each time. Also avoids the hassle of passing around variables. + * + * @static + * @param string $class name of the class + * @return object instance of the class + */ + public static function getInstance($class = false) + { + // In < 5.3 arguments must match in child, hence defaulting $class + // @todo Remove this, as we're no longer supporting 5.3 + if ($class == false) + { + return false; + } + else + { + if (!isset(self::$instances[$class])) + { + self::$instances[$class] = new $class(); + } - return self::$instances[$class]; - } - } + return self::$instances[$class]; + } + } - /** - * Destructor - */ - public function __destruct() - { - // Optionally logs the destructor to the profiler - if ($this->profiler === true || ((is_array($this->profiler) && in_array('objects', $this->profiler)) || stripos($this->profiler, 'objects') !== false)) - { - Profiler::log($this, '__destruct'); - } - } + /** + * Destructor + */ + public function __destruct() + { + // Optionally logs the destructor to the profiler + if ($this->profiler === true || ((is_array($this->profiler) && in_array('objects', $this->profiler)) || stripos($this->profiler, 'objects') !== false)) + { + Profiler::log($this, '__destruct'); + } + } } -?> diff --git a/src/classes/Profiler.php b/src/classes/Profiler.php index fff7aaa..c5a8e88 100644 --- a/src/classes/Profiler.php +++ b/src/classes/Profiler.php @@ -33,358 +33,357 @@ */ class Profiler { - /** - * Profile - * - * Array of logged events - * - * @static - * @access private - * @var array - */ - private static $profile = []; + /** + * Profile + * + * Array of logged events + * + * @static + * @access private + * @var array + */ + private static $profile = []; - /** - * Queries - * - * Number of queries that have been logged - * - * @static - * @access private - * @var integer - */ - private static $queries = 0; + /** + * Queries + * + * Number of queries that have been logged + * + * @static + * @access private + * @var integer + */ + private static $queries = 0; - /** - * Timers - * - * Array of active timers - * - * @static - * @access private - * @var array - */ - private static $timers = []; + /** + * Timers + * + * Array of active timers + * + * @static + * @access private + * @var array + */ + private static $timers = []; - /** - * Enabled - * - * Checks if the profiler is set to boolean true or if the passed type is - * specified in the profiler configuration value. - * - * @param array $type type(s) to check - * @return boolean whether or not the type is enabled - */ - public static function enabled(/* polymorphic */) - { - $config = Config::getInstance(); - $config = isset($config->pickles['profiler']) ? $config->pickles['profiler'] : false; + /** + * Enabled + * + * Checks if the profiler is set to boolean true or if the passed type is + * specified in the profiler configuration value. + * + * @param array $type type(s) to check + * @return boolean whether or not the type is enabled + */ + public static function enabled(/* polymorphic */) + { + $config = Config::getInstance(); + $config = isset($config->pickles['profiler']) ? $config->pickles['profiler'] : false; - // Checks if we're set to boolean true - if ($config === true) - { - return true; - } - else - { - $types = func_get_args(); + // Checks if we're set to boolean true + if ($config === true) + { + return true; + } + else + { + $types = func_get_args(); - foreach ($types as $type) - { - if (stripos($config, $type) !== false) - { - return true; - } - } - } + foreach ($types as $type) + { + if (stripos($config, $type) !== false) + { + return true; + } + } + } - return false; - } + return false; + } - /** - * Log - * - * Logs the event to be displayed later on. Due to the nature of how much - * of a pain it is to determine which class method called this method I - * opted to make the method a passable argument for ease of use. Perhaps - * I'll revisit in the future. Handles all elapsed time calculations and - * memory usage. - * - * @static - * @param mixed $data data to log - * @param string $method name of the class method being logged - */ - public static function log($data, $method = false, $type = false) - { - $time = microtime(true); - $data_type = ($data == 'timer' ? $data : gettype($data)); + /** + * Log + * + * Logs the event to be displayed later on. Due to the nature of how much + * of a pain it is to determine which class method called this method I + * opted to make the method a passable argument for ease of use. Perhaps + * I'll revisit in the future. Handles all elapsed time calculations and + * memory usage. + * + * @static + * @param mixed $data data to log + * @param string $method name of the class method being logged + */ + public static function log($data, $method = false, $type = false) + { + $time = microtime(true); + $data_type = ($data == 'timer' ? $data : gettype($data)); - // Tidys the data by type - switch ($data_type) - { - case 'array': - $log = '
' . print_r($data, true) . '
'; - break; + // Tidys the data by type + switch ($data_type) + { + case 'array': + $log = '
' . print_r($data, true) . '
'; + break; - case 'object': - $log = '[' . get_parent_class($data) . '] ' - . '' . get_class($data) . '' - . ($method != '' ? '->' . $method . '()' : ''); + case 'object': + $log = '[' . get_parent_class($data) . '] ' + . '' . get_class($data) . '' + . ($method != '' ? '->' . $method . '()' : ''); - $data_type = '' . $data_type . ''; - break; + $data_type = '' . $data_type . ''; + break; - case 'timer': - $log = $method; + case 'timer': + $log = $method; - $data_type = '' . $data_type . ''; - break; + $data_type = '' . $data_type . ''; + break; - case 'string': - default: - if ($type != false) - { - $data_type = $type; - } + case 'string': + default: + if ($type != false) + { + $data_type = $type; + } - $log = $data; - break; - } + $log = $data; + break; + } - self::$profile[] = [ - 'log' => $log, - 'type' => $data_type, - 'time' => $time, - 'elapsed' => $time - $_SERVER['REQUEST_TIME_FLOAT'], - 'memory' => memory_get_usage(), - ]; - } + self::$profile[] = [ + 'log' => $log, + 'type' => $data_type, + 'time' => $time, + 'elapsed' => $time - $_SERVER['REQUEST_TIME_FLOAT'], + 'memory' => memory_get_usage(), + ]; + } - /** - * Log Query - * - * Serves as a wrapper to get query data to the log function - * - * @static - * @param string $query the query being executed - * @param array $input_parameters optional prepared statement data - * @param array $explain EXPLAIN data for the query - * @param float $duration the speed of the query - */ - public static function logQuery($query, $input_parameters = false, $explain = false, $duration = false) - { - self::$queries++; + /** + * Log Query + * + * Serves as a wrapper to get query data to the log function + * + * @static + * @param string $query the query being executed + * @param array $input_parameters optional prepared statement data + * @param array $explain EXPLAIN data for the query + * @param float $duration the speed of the query + */ + public static function logQuery($query, $input_parameters = false, $explain = false, $duration = false) + { + self::$queries++; - $log = ''; + $log = ''; - if ($input_parameters != 'false' && is_array($input_parameters)) - { - $log .= '
'; + if ($input_parameters != 'false' && is_array($input_parameters)) + { + $log .= '
'; - foreach ($input_parameters as $key => $value) - { - $log .= '
' . $key . ' => ' . $value . ''; + foreach ($input_parameters as $key => $value) + { + $log .= '
' . $key . ' => ' . $value . ''; - $query = str_replace($key, '' . $key . '', $query); - } - } + $query = str_replace($key, '' . $key . '', $query); + } + } - $log = '' . $query . '' . $log; + $log = '' . $query . '' . $log; - if (is_array($explain)) - { - $log .= '
'; + if (is_array($explain)) + { + $log .= '
'; - foreach ($explain as $table) - { - $log .= '
Possible Keys => ' . ($table['possible_keys'] == '' ? 'NONE' : $table['possible_keys']) . '' - . '
Key => ' . ($table['key'] == '' ? 'NONE' : $table['key']) . '' - . '
Type => ' . $table['type'] . '' - . '
Rows => ' . $table['rows'] . '' - . ($table['Extra'] != '' ? '
Extra => ' . $table['Extra'] . '' : ''); - } - } + foreach ($explain as $table) + { + $log .= '
Possible Keys => ' . ($table['possible_keys'] == '' ? 'NONE' : $table['possible_keys']) . '' + . '
Key => ' . ($table['key'] == '' ? 'NONE' : $table['key']) . '' + . '
Type => ' . $table['type'] . '' + . '
Rows => ' . $table['rows'] . '' + . ($table['Extra'] != '' ? '
Extra => ' . $table['Extra'] . '' : ''); + } + } - $log .= '

Speed: ' . number_format($duration * 100, 3) . ' ms'; + $log .= '

Speed: ' . number_format($duration * 100, 3) . ' ms'; - self::log($log, false, 'database'); - } + self::log($log, false, 'database'); + } - /** - * Timer - * - * Logs the start and end of a timer. - * - * @param string $timer name of the timer - * @return boolean whether or not timer profiling is enabled - */ - public static function timer($timer) - { - if (self::enabled('timers')) - { - // Starts the timer - if (!isset(self::$timers[$timer])) - { - self::$timers[$timer] = microtime(true); - self::Log('timer', 'Started timer ' . $timer . ''); - } - // Ends the timer - else - { - self::Log('timer', 'Stopped timer ' . $timer . ' => Time Elapsed: ' . number_format((microtime(true) - self::$timers[$timer]) * 100, 3) . ' ms'); + /** + * Timer + * + * Logs the start and end of a timer. + * + * @param string $timer name of the timer + * @return boolean whether or not timer profiling is enabled + */ + public static function timer($timer) + { + if (self::enabled('timers')) + { + // Starts the timer + if (!isset(self::$timers[$timer])) + { + self::$timers[$timer] = microtime(true); + self::Log('timer', 'Started timer ' . $timer . ''); + } + // Ends the timer + else + { + self::Log('timer', 'Stopped timer ' . $timer . ' => Time Elapsed: ' . number_format((microtime(true) - self::$timers[$timer]) * 100, 3) . ' ms'); - unset(self::$timers[$timer]); - } + unset(self::$timers[$timer]); + } - return true; - } + return true; + } - return false; - } + return false; + } - /** - * Report - * - * Generates the Profiler report that is displayed by the Controller. - * Contains all the HTML needed to display the data properly inline on the - * page. Will generally be displayed after the closing HTML tag. - * - * @todo Thinking this should return the report and not necessarily echo it - */ - public static function report() - { - ?> - -
- PICKLES Profiler

- There is nothing to profile. This often happens when the profiler configuration is set to either "queries" or "explains" and there are no database queries on the page (common on pages that only have a template). You may want to set the profiler to boolean true to ensure you get a profile of the page.'; - } - else - { - $start_time = $_SERVER['REQUEST_TIME_FLOAT']; - $peak_usage = self::formatSize(memory_get_peak_usage()); - $end_time = self::$profile[count(self::$profile) - 1]['time']; // @todo No idea what though? - $duration = ($end_time - $start_time); + /** + * Report + * + * Generates the Profiler report that is displayed by the Controller. + * Contains all the HTML needed to display the data properly inline on the + * page. Will generally be displayed after the closing HTML tag. + * + * @todo Thinking this should return the report and not necessarily echo it + */ + public static function report() + { + ?> + +
+ PICKLES Profiler

+ There is nothing to profile. This often happens when the profiler configuration is set to either "queries" or "explains" and there are no database queries on the page (common on pages that only have a template). You may want to set the profiler to boolean true to ensure you get a profile of the page.'; + } + else + { + $start_time = $_SERVER['REQUEST_TIME_FLOAT']; + $peak_usage = self::formatSize(memory_get_peak_usage()); + $end_time = self::$profile[count(self::$profile) - 1]['time']; // @todo No idea what though? + $duration = ($end_time - $start_time); - $logs = count(self::$profile); - $logs .= ' Log' . ($logs == 1 ? '' : 's'); + $logs = count(self::$profile); + $logs .= ' Log' . ($logs == 1 ? '' : 's'); - $files = count(get_included_files()); - $files .= ' File' . ($files == 1 ? '' : 's'); + $files = count(get_included_files()); + $files .= ' File' . ($files == 1 ? '' : 's'); - $queries = self::$queries . ' Quer'. (self::$queries == 1 ? 'y' : 'ies'); - ?> - - - - - - - - -
- Console -
-
- Load Time -
-
- Memory Usage -
-
- Database -
-
- Includes -
-
- - - - - - - $entry) - { - ?> - - - - - - - -
ConsoleMemoryTime
ms
- -
-

- + + + + + + + + +
+ Console +
+
+ Load Time +
+
+ Memory Usage +
+
+ Database +
+
+ Includes +
+
+ + + + + + + $entry) + { + ?> + + + + + + + +
ConsoleMemoryTime
ms
+ +
+

+ diff --git a/src/classes/Security.php b/src/classes/Security.php index e09ef20..3e2e4c5 100644 --- a/src/classes/Security.php +++ b/src/classes/Security.php @@ -26,318 +26,317 @@ */ class Security { - /** - * Lookup Cache - * - * Used to minimize database lookups - * - * @static - * @access private - * @var array - */ - private static $cache = []; + /** + * Lookup Cache + * + * Used to minimize database lookups + * + * @static + * @access private + * @var array + */ + private static $cache = []; - /** - * Generate Hash - * - * Generates an SHA1 hash from the provided string. Salt optional. - * - * @param string $source value to hash - * @param mixed $salts optional salt or salts - * @return string SHA1 hash - * @todo Transition away from this - */ - public static function generateHash($source, $salts = null) - { - // Determines which salt(s) to use - if ($salts == null) - { - $config = Config::getInstance(); + /** + * Generate Hash + * + * Generates an SHA1 hash from the provided string. Salt optional. + * + * @param string $source value to hash + * @param mixed $salts optional salt or salts + * @return string SHA1 hash + * @todo Transition away from this + */ + public static function generateHash($source, $salts = null) + { + // Determines which salt(s) to use + if ($salts == null) + { + $config = Config::getInstance(); - if (isset($config->security['salt']) && $config->security['salt'] != null) - { - $salts = $config->security['salt']; - } - else - { - $salts = ['P1ck73', 'Ju1C3']; - } - } + if (isset($config->security['salt']) && $config->security['salt'] != null) + { + $salts = $config->security['salt']; + } + else + { + $salts = ['P1ck73', 'Ju1C3']; + } + } - // Forces the variable to be an array - if (!is_array($salts)) - { - $salts = [$salts]; - } + // Forces the variable to be an array + if (!is_array($salts)) + { + $salts = [$salts]; + } - // Loops through the salts, applies them and calculates the hash - $hash = $source; + // Loops through the salts, applies them and calculates the hash + $hash = $source; - foreach ($salts as $salt) - { - $hash = sha1($salt . $hash); - } + foreach ($salts as $salt) + { + $hash = sha1($salt . $hash); + } - return $hash; - } + return $hash; + } - /** - * Generate SHA-256 Hash - * - * Generates an SHA-256 hash from the provided string and salt. Borrowed the - * large iteration logic from fCryptography::hashWithSalt() as, and I quote, - * "makes rainbow table attacks infesible". - * - * @param string $source value to hash - * @param mixed $salt value to use as salt - * @return string SHA-256 hash - * @link https://github.com/flourishlib/flourish-classes/blob/master/fCryptography.php - */ - public static function generateSHA256Hash($source, $salt) - { - $sha256 = sha1($salt . $source); + /** + * Generate SHA-256 Hash + * + * Generates an SHA-256 hash from the provided string and salt. Borrowed the + * large iteration logic from fCryptography::hashWithSalt() as, and I quote, + * "makes rainbow table attacks infesible". + * + * @param string $source value to hash + * @param mixed $salt value to use as salt + * @return string SHA-256 hash + * @link https://github.com/flourishlib/flourish-classes/blob/master/fCryptography.php + */ + public static function generateSHA256Hash($source, $salt) + { + $sha256 = sha1($salt . $source); - for ($i = 0; $i < 1000; $i++) - { - $sha256 = hash('sha256', $sha256 . (($i % 2 == 0) ? $source : $salt)); - } + for ($i = 0; $i < 1000; $i++) + { + $sha256 = hash('sha256', $sha256 . (($i % 2 == 0) ? $source : $salt)); + } - return $sha256; - } + return $sha256; + } - /** - * Check Session - * - * Checks if sessions are enabled. - * - * @static - * @access private - * @return boolean whether or not sessions are enabled - */ - private static function checkSession() - { - if (session_id() == '') - { - return false; - } - else - { - return true; - } - } + /** + * Check Session + * + * Checks if sessions are enabled. + * + * @static + * @access private + * @return boolean whether or not sessions are enabled + */ + private static function checkSession() + { + if (session_id() == '') + { + return false; + } + else + { + return true; + } + } - /** - * Check Level - * - * Checks if a passed level is an integer and/or properly defined in the - * site's configuration file. - * - * @static - * @access private - * @param mixed access level to validate - * @return whether ot not the access level is valid - */ - private static function checkLevel(&$access_level) - { - return is_int($access_level); - } + /** + * Check Level + * + * Checks if a passed level is an integer and/or properly defined in the + * site's configuration file. + * + * @static + * @access private + * @param mixed access level to validate + * @return whether ot not the access level is valid + */ + private static function checkLevel(&$access_level) + { + return is_int($access_level); + } - /** - * Login - * - * Creates a session variable containing the user ID and generated token. - * The token is also assigned to a cookie to be used when validating the - * security level. When the level value is present, the class will by pass - * the database look up and simply use that value when validating (the less - * paranoid scenario). - * - * @static - * @param integer $user_id ID of the user that's been logged in - * @param integer $level optional level for the user being logged in - * @param string $role textual representation of the user's level - * @return boolean whether or not the login could be completed - */ - public static function login($user_id, $level = null, $role = null) - { - if (self::checkSession()) - { - $token = sha1(microtime()); + /** + * Login + * + * Creates a session variable containing the user ID and generated token. + * The token is also assigned to a cookie to be used when validating the + * security level. When the level value is present, the class will by pass + * the database look up and simply use that value when validating (the less + * paranoid scenario). + * + * @static + * @param integer $user_id ID of the user that's been logged in + * @param integer $level optional level for the user being logged in + * @param string $role textual representation of the user's level + * @return boolean whether or not the login could be completed + */ + public static function login($user_id, $level = null, $role = null) + { + if (self::checkSession()) + { + $token = sha1(microtime()); - $_SESSION['__pickles']['security'] = [ - 'token' => $token, - 'user_id' => (int)$user_id, - 'level' => $level, - 'role' => $role, - ]; + $_SESSION['__pickles']['security'] = [ + 'token' => $token, + 'user_id' => (int)$user_id, + 'level' => $level, + 'role' => $role, + ]; - setcookie('pickles_security_token', $token); + setcookie('pickles_security_token', $token); - return true; - } - else - { - return false; - } - } + return true; + } + else + { + return false; + } + } - /** - * Logout - * - * Clears out the security information in the session and the cookie. - * - * @static - * @return boolean true - */ - public static function logout() - { - if (isset($_SESSION['__pickles']['security'])) - { - $_SESSION['__pickles']['security'] = null; - unset($_SESSION['__pickles']['security']); + /** + * Logout + * + * Clears out the security information in the session and the cookie. + * + * @static + * @return boolean true + */ + public static function logout() + { + if (isset($_SESSION['__pickles']['security'])) + { + $_SESSION['__pickles']['security'] = null; + unset($_SESSION['__pickles']['security']); - setcookie('pickles_security_token', '', time() - 3600); - } + setcookie('pickles_security_token', '', time() - 3600); + } - return true; - } + return true; + } - /** - * Get User Level - * - * Looks up the user level in the database and caches it. Cache is used - * for any subsequent look ups for the user. Also validates the session - * variable against the cookie to ensure everything is legit. If the user - * level is set in the session, that value will take precedence. - * - * return integer user level or false - */ - private static function getUserLevel() - { - if (self::checkSession() == true && isset($_SESSION['__pickles']['security']['user_id'])) - { - // Checks the session against the cookie - if (isset($_SESSION['__pickles']['security']['token'], $_COOKIE['pickles_security_token']) - && $_SESSION['__pickles']['security']['token'] != $_COOKIE['pickles_security_token']) - { - Security::logout(); - } - elseif (isset($_SESSION['__pickles']['security']['level']) && $_SESSION['__pickles']['security']['level'] != null) - { - return $_SESSION['__pickles']['security']['level']; - } - // Used to hit the database to determine the user's level, found it - // to be overkill and just opted for a simple logout. - else - { - Security::logout(); - } - } + /** + * Get User Level + * + * Looks up the user level in the database and caches it. Cache is used + * for any subsequent look ups for the user. Also validates the session + * variable against the cookie to ensure everything is legit. If the user + * level is set in the session, that value will take precedence. + * + * return integer user level or false + */ + private static function getUserLevel() + { + if (self::checkSession() == true && isset($_SESSION['__pickles']['security']['user_id'])) + { + // Checks the session against the cookie + if (isset($_SESSION['__pickles']['security']['token'], $_COOKIE['pickles_security_token']) + && $_SESSION['__pickles']['security']['token'] != $_COOKIE['pickles_security_token']) + { + Security::logout(); + } + elseif (isset($_SESSION['__pickles']['security']['level']) && $_SESSION['__pickles']['security']['level'] != null) + { + return $_SESSION['__pickles']['security']['level']; + } + // Used to hit the database to determine the user's level, found it + // to be overkill and just opted for a simple logout. + else + { + Security::logout(); + } + } - return false; - } + return false; + } - /** - * Is Level - * - * Checks the user's access level is exactly the passed level - * - * @static - * @param integer $access_level access level to be checked against - * @return boolean whether or not the user is that level - */ - public static function isLevel() - { - $is_level = false; + /** + * Is Level + * + * Checks the user's access level is exactly the passed level + * + * @static + * @param integer $access_level access level to be checked against + * @return boolean whether or not the user is that level + */ + public static function isLevel() + { + $is_level = false; - if (self::checkSession()) - { - $arguments = func_get_args(); - if (is_array($arguments[0])) - { - $arguments = $arguments[0]; - } + if (self::checkSession()) + { + $arguments = func_get_args(); + if (is_array($arguments[0])) + { + $arguments = $arguments[0]; + } - foreach ($arguments as $access_level) - { - if (self::checkLevel($access_level)) - { - if (self::getUserLevel() == $access_level) - { - $is_level = true; - } - } - } - } + foreach ($arguments as $access_level) + { + if (self::checkLevel($access_level)) + { + if (self::getUserLevel() == $access_level) + { + $is_level = true; + } + } + } + } - return $is_level; - } + return $is_level; + } - /** - * Has Level - * - * Checks the user's access level against the passed level. - * - * @static - * @param integer $access_level access level to be checked against - * @return boolean whether or not the user has access - */ - public static function hasLevel() - { - $has_level = false; + /** + * Has Level + * + * Checks the user's access level against the passed level. + * + * @static + * @param integer $access_level access level to be checked against + * @return boolean whether or not the user has access + */ + public static function hasLevel() + { + $has_level = false; - if (self::checkSession()) - { - $arguments = func_get_args(); + if (self::checkSession()) + { + $arguments = func_get_args(); - if (is_array($arguments[0])) - { - $arguments = $arguments[0]; - } + if (is_array($arguments[0])) + { + $arguments = $arguments[0]; + } - foreach ($arguments as $access_level) - { - if (self::checkLevel($access_level)) - { - if (self::getUserLevel() >= $access_level) - { - $has_level = true; - } - } - } - } + foreach ($arguments as $access_level) + { + if (self::checkLevel($access_level)) + { + if (self::getUserLevel() >= $access_level) + { + $has_level = true; + } + } + } + } - return $has_level; - } + return $has_level; + } - /** - * Between Level - * - * Checks the user's access level against the passed range. - * - * @static - * @param integer $low access level to be checked against - * @param integer $high access level to be checked against - * @return boolean whether or not the user has access - */ - public static function betweenLevel($low, $high) - { - $between_level = false; + /** + * Between Level + * + * Checks the user's access level against the passed range. + * + * @static + * @param integer $low access level to be checked against + * @param integer $high access level to be checked against + * @return boolean whether or not the user has access + */ + public static function betweenLevel($low, $high) + { + $between_level = false; - if (self::checkSession()) - { - if (self::checkLevel($low) && self::checkLevel($high)) - { - $user_level = self::getUserLevel(); + if (self::checkSession()) + { + if (self::checkLevel($low) && self::checkLevel($high)) + { + $user_level = self::getUserLevel(); - if ($user_level >= $low && $user_level <= $high) - { - $between_level = true; - } - } - } + if ($user_level >= $low && $user_level <= $high) + { + $between_level = true; + } + } + } - return $between_level; - } + return $between_level; + } } -?> diff --git a/src/classes/Session.php b/src/classes/Session.php index 23b5a05..62b6869 100644 --- a/src/classes/Session.php +++ b/src/classes/Session.php @@ -26,101 +26,100 @@ */ class Session extends Object { - /** - * Constructor - * - * All of our set up logic for the session in contained here. This class is - * initially instantiated from pickles.php. Non-file handlers need to be - * configured in the site's config. MySQL support was dropped in favor of - * in memory stores or simply relying on file based sessions. Why? Because - * using MySQL for sessions is very write intensive and having done it in - * the past I don't recommend it. If you run a single server, files are - * good enough if your volume is lower. Memcache[d] is fine if you don't - * mind logging all of your users off your site when you restart the - * service and/or you run out of memory for the process. Redis is the best - * choice as it can be configured to be persistent and lives in memory. - * This is assuming you don't just want to roll your own sessions, which is - * pretty damn easy as well. - */ - public function __construct() - { - if (isset($_SERVER['REQUEST_METHOD'])) - { - parent::__construct(); + /** + * Constructor + * + * All of our set up logic for the session in contained here. This class is + * initially instantiated from pickles.php. Non-file handlers need to be + * configured in the site's config. MySQL support was dropped in favor of + * in memory stores or simply relying on file based sessions. Why? Because + * using MySQL for sessions is very write intensive and having done it in + * the past I don't recommend it. If you run a single server, files are + * good enough if your volume is lower. Memcache[d] is fine if you don't + * mind logging all of your users off your site when you restart the + * service and/or you run out of memory for the process. Redis is the best + * choice as it can be configured to be persistent and lives in memory. + * This is assuming you don't just want to roll your own sessions, which is + * pretty damn easy as well. + */ + public function __construct() + { + if (isset($_SERVER['REQUEST_METHOD'])) + { + parent::__construct(); - // Sets up our configuration variables - if (isset($this->config->pickles['sessions'])) - { - $session = $this->config->pickles['sessions']; - } + // Sets up our configuration variables + if (isset($this->config->pickles['sessions'])) + { + $session = $this->config->pickles['sessions']; + } - $datasources = $this->config->datasources; - $handler = 'files'; - $datasource = false; + $datasources = $this->config->datasources; + $handler = 'files'; + $datasource = false; - if (isset($session, $datasources[$session])) - { - $datasource = $datasources[$session]; - $handler = $datasource['type']; + if (isset($session, $datasources[$session])) + { + $datasource = $datasources[$session]; + $handler = $datasource['type']; - if ($handler != 'files') - { - if (isset($datasource['hostname'], $datasource['port'])) - { - $host = ($handler != 'memcached' ? 'tcp://' : '') - . $datasource['hostname'] . ':' . $datasource['port']; - } - else - { - throw new Exception('You must provide both the hostname and port for the datasource.'); - } - } - } + if ($handler != 'files') + { + if (isset($datasource['hostname'], $datasource['port'])) + { + $host = ($handler != 'memcached' ? 'tcp://' : '') + . $datasource['hostname'] . ':' . $datasource['port']; + } + else + { + throw new Exception('You must provide both the hostname and port for the datasource.'); + } + } + } - switch ($handler) - { - case 'memcache': - ini_set('session.save_handler', 'memcache'); - ini_set('session.save_path', $host . '?persistent=1&weight=1&timeout=1&retry_interval=15'); - break; + switch ($handler) + { + case 'memcache': + ini_set('session.save_handler', 'memcache'); + ini_set('session.save_path', $host . '?persistent=1&weight=1&timeout=1&retry_interval=15'); + break; - case 'memcached': - ini_set('session.save_handler', 'memcached'); - ini_set('session.save_path', $host); - break; + case 'memcached': + ini_set('session.save_handler', 'memcached'); + ini_set('session.save_path', $host); + break; - case 'redis': - $save_path = $host . '?weight=1'; + case 'redis': + $save_path = $host . '?weight=1'; - // Database ignored by phpredis when this was coded - if (isset($datasource['database'])) - { - $save_path .= '&database=' . $datasource['database']; - } + // Database ignored by phpredis when this was coded + if (isset($datasource['database'])) + { + $save_path .= '&database=' . $datasource['database']; + } - if (isset($datasource['prefix'])) - { - $save_path .= '&prefix=' . $datasource['prefix']; - } + if (isset($datasource['prefix'])) + { + $save_path .= '&prefix=' . $datasource['prefix']; + } - ini_set('session.save_handler', 'redis'); - ini_set('session.save_path', $save_path); - break; + ini_set('session.save_handler', 'redis'); + ini_set('session.save_path', $save_path); + break; - case 'files': - ini_set('session.save_handler', 'files'); - break; - } + case 'files': + ini_set('session.save_handler', 'files'); + break; + } - // Don't start sessions for people without a user agent and bots. - if (isset($_SERVER['HTTP_USER_AGENT']) - && !String::isEmpty($_SERVER['HTTP_USER_AGENT']) - && !preg_match('/(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg)/i', $_SERVER['HTTP_USER_AGENT'])) - { - session_start(); - } - } - } + // Don't start sessions for people without a user agent and bots. + if (isset($_SERVER['HTTP_USER_AGENT']) + && !String::isEmpty($_SERVER['HTTP_USER_AGENT']) + && !preg_match('/(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg)/i', $_SERVER['HTTP_USER_AGENT'])) + { + session_start(); + } + } + } } -?> diff --git a/src/classes/Sort.php b/src/classes/Sort.php index 8b6ac58..ff01ec9 100644 --- a/src/classes/Sort.php +++ b/src/classes/Sort.php @@ -23,50 +23,49 @@ */ class Sort { - /** - * Ascending - * - * Variable to utilize ascending sort - * - * @var integer - */ - const ASC = 'ASC'; + /** + * Ascending + * + * Variable to utilize ascending sort + * + * @var integer + */ + const ASC = 'ASC'; - /** - * Descending - * - * Variable to utilize descending sort - * - * @var integer - */ - const DESC = 'DESC'; + /** + * Descending + * + * Variable to utilize descending sort + * + * @var integer + */ + const DESC = 'DESC'; - /** - * Sort By - * - * Sorts an array by the specified column, optionally in either direction. - * - * @param string $field field to sort by - * @param array $array array to sort - * @param string $direction optional direction to sort - * @retun boolean true because sorting is done by reference - */ - public static function by($field, &$array, $direction = Sort::ASC) - { - usort($array, create_function('$a, $b', ' - $a = $a["' . $field . '"]; - $b = $b["' . $field . '"]; + /** + * Sort By + * + * Sorts an array by the specified column, optionally in either direction. + * + * @param string $field field to sort by + * @param array $array array to sort + * @param string $direction optional direction to sort + * @retun boolean true because sorting is done by reference + */ + public static function by($field, &$array, $direction = Sort::ASC) + { + usort($array, create_function('$a, $b', ' + $a = $a["' . $field . '"]; + $b = $b["' . $field . '"]; - if ($a == $b) - { - return 0; - } + if ($a == $b) + { + return 0; + } - return ($a ' . ($direction == Sort::DESC ? '>' : '<') .' $b) ? -1 : 1; - ')); + return ($a ' . ($direction == Sort::DESC ? '>' : '<') .' $b) ? -1 : 1; + ')); - return true; - } + return true; + } } -?> diff --git a/src/classes/String.php b/src/classes/String.php index f333c32..0609079 100644 --- a/src/classes/String.php +++ b/src/classes/String.php @@ -23,244 +23,243 @@ */ class String { - // {{{ Format Phone Number + // {{{ Format Phone Number - /** - * Format Phone Number - * - * Formats a 10 digit phone number with dashes as ###-###-####. - * - * @static - * @param string $number number to format - * @param string $replacement output of the string - * @return string formatted phone number - */ - public static function formatPhoneNumber($number, $replacement = '$1-$2-$3') - { - // Strips characters we don't need - $number = str_replace(['(', ')', ' ', '-', '.', '_'], '', $number); + /** + * Format Phone Number + * + * Formats a 10 digit phone number with dashes as ###-###-####. + * + * @static + * @param string $number number to format + * @param string $replacement output of the string + * @return string formatted phone number + */ + public static function formatPhoneNumber($number, $replacement = '$1-$2-$3') + { + // Strips characters we don't need + $number = str_replace(['(', ')', ' ', '-', '.', '_'], '', $number); - // Formats the number - return preg_replace('/^(\d{3})(\d{3})(.+)$/', $replacement, $number); - } + // Formats the number + return preg_replace('/^(\d{3})(\d{3})(.+)$/', $replacement, $number); + } - // }}} - // {{{ Generate Gravatar Hash + // }}} + // {{{ Generate Gravatar Hash - /** - * Generate Gravatar Hash - * - * Generates a hash from the passed string that can then be used for - * fetching an avatar from Gravatar.com - * - * @deprecated - * @static - * @param string $string string to hash, should be an email address - * @return string resulting hash - */ - public static function generateGravatarHash($string) - { - return API_Gravatar::hash($string); - } + /** + * Generate Gravatar Hash + * + * Generates a hash from the passed string that can then be used for + * fetching an avatar from Gravatar.com + * + * @deprecated + * @static + * @param string $string string to hash, should be an email address + * @return string resulting hash + */ + public static function generateGravatarHash($string) + { + return API_Gravatar::hash($string); + } - // }}} - // {{{ Generate Slug + // }}} + // {{{ Generate Slug - /** - * Generate Slug - * - * Generates a slug from the pass string by lowercasing the string, - * trimming whitespace and converting non-alphanumeric values to - * dashes. Takes care of multiple dashes as well. - * - * @static - * @param string $string to be converted to the slug - * @return string resulting slug - */ - public static function generateSlug($string) - { - $string = strtolower(trim($string)); - $string = preg_replace('/[^a-z0-9-]/', '-', $string); - $string = preg_replace('/-+/', '-', $string); - return trim($string, '-');; - } + /** + * Generate Slug + * + * Generates a slug from the pass string by lowercasing the string, + * trimming whitespace and converting non-alphanumeric values to + * dashes. Takes care of multiple dashes as well. + * + * @static + * @param string $string to be converted to the slug + * @return string resulting slug + */ + public static function generateSlug($string) + { + $string = strtolower(trim($string)); + $string = preg_replace('/[^a-z0-9-]/', '-', $string); + $string = preg_replace('/-+/', '-', $string); + return trim($string, '-');; + } - // }}} - // {{{ Is Empty + // }}} + // {{{ Is Empty - /** - * Is Empty - * - * Checks if a string is empty. You can use the PHP function empty() - * but that returns true for a string of "0". Last I checked, that's - * not an empty string. PHP's function also doesn't apply trim() to the - * value to ensure it's not just a bunch of spaces. - * - * @static - * @param string $value string(s) to be checked - * @return boolean whether or not the string is empty - */ - public static function isEmpty() - { - foreach (func_get_args() as $value) - { - if (trim($value) == '') - { - return true; - } - } + /** + * Is Empty + * + * Checks if a string is empty. You can use the PHP function empty() + * but that returns true for a string of "0". Last I checked, that's + * not an empty string. PHP's function also doesn't apply trim() to the + * value to ensure it's not just a bunch of spaces. + * + * @static + * @param string $value string(s) to be checked + * @return boolean whether or not the string is empty + */ + public static function isEmpty() + { + foreach (func_get_args() as $value) + { + if (trim($value) == '') + { + return true; + } + } - return false; - } + return false; + } - // }}} - // {{{ Pluralize + // }}} + // {{{ Pluralize - /** - * Pluralize - * - * Based on a passed integer, the word will be pluralized. A value of - * zero will also pluralize the word (e.g. 0 things not 0 thing). - * - * @static - * @param string $string the word to plurailze - * @param integer $count the count to interrogate - * @param boolean $both (optional) include count in return - * @return string pluralized word - */ - public static function pluralize($string, $count, $both = false) - { - if ($count != 1) - { - $string .= 's'; - } + /** + * Pluralize + * + * Based on a passed integer, the word will be pluralized. A value of + * zero will also pluralize the word (e.g. 0 things not 0 thing). + * + * @static + * @param string $string the word to plurailze + * @param integer $count the count to interrogate + * @param boolean $both (optional) include count in return + * @return string pluralized word + */ + public static function pluralize($string, $count, $both = false) + { + if ($count != 1) + { + $string .= 's'; + } - if ($both) - { - $string = $count . ' ' . $string; - } + if ($both) + { + $string = $count . ' ' . $string; + } - return $string; - } + return $string; + } - // }}} - // {{{ Random + // }}} + // {{{ Random - /** - * Random - * - * Generates a pseudo-random string based on the passed parameters. - * - * Note: Similar characters = 0, O, 1, I (and may be expanded) - * - * @static - * @param integer $length optional length of the generated string - * @param boolean $alpha optional include alpha characters - * @param boolean $numeric optional include numeric characters - * @param boolean $similar optional include similar characters - * @return string generated string - */ - public static function random($length = 8, $alpha = true, $numeric = true, $similar = true) - { - $characters = []; - $string = ''; + /** + * Random + * + * Generates a pseudo-random string based on the passed parameters. + * + * Note: Similar characters = 0, O, 1, I (and may be expanded) + * + * @static + * @param integer $length optional length of the generated string + * @param boolean $alpha optional include alpha characters + * @param boolean $numeric optional include numeric characters + * @param boolean $similar optional include similar characters + * @return string generated string + */ + public static function random($length = 8, $alpha = true, $numeric = true, $similar = true) + { + $characters = []; + $string = ''; - // Adds alpha characters to the list - if ($alpha == true) - { - if ($similar == true) - { - $characters = array_merge($characters, range('a', 'z')); - } - else - { - $characters = array_merge($characters, range('a', 'h'), range('j', 'n'), range('p', 'z')); - } - } + // Adds alpha characters to the list + if ($alpha == true) + { + if ($similar == true) + { + $characters = array_merge($characters, range('a', 'z')); + } + else + { + $characters = array_merge($characters, range('a', 'h'), range('j', 'n'), range('p', 'z')); + } + } - // Adds numeric characters to the list - if ($numeric == true) - { - if ($similar == true) - { - $characters = array_merge($characters, range('0', '9')); - } - else - { - $characters = array_merge($characters, range('2', '9')); - } - } + // Adds numeric characters to the list + if ($numeric == true) + { + if ($similar == true) + { + $characters = array_merge($characters, range('0', '9')); + } + else + { + $characters = array_merge($characters, range('2', '9')); + } + } - if (count($characters) > 0) - { - shuffle($characters); + if (count($characters) > 0) + { + shuffle($characters); - for ($i = 0; $i < $length; $i++) - { - $string .= $characters[array_rand($characters)]; - } - } + for ($i = 0; $i < $length; $i++) + { + $string .= $characters[array_rand($characters)]; + } + } - return $string; - } + return $string; + } - // }}} - // {{{ Truncate + // }}} + // {{{ Truncate - /** - * Truncate - * - * Truncates a string to a specified length and (optionally) adds a - * span to provide a rollover to see the expanded text. - * - * @static - * @param string $string string to truncate - * @param integer $length length to truncate to - * @param boolean $hover (optional) whether or not to add the rollover - * @return string truncate string - */ - public static function truncate($string, $length, $hover = true) - { - if (strlen($string) > $length) - { - if ($hover == true) - { - $string = '' . mb_strcut($string, 0, $length, 'UTF-8') . '…'; - } - else - { - $string = mb_strcut($string, 0, $length, 'UTF-8') . '…'; - } - } + /** + * Truncate + * + * Truncates a string to a specified length and (optionally) adds a + * span to provide a rollover to see the expanded text. + * + * @static + * @param string $string string to truncate + * @param integer $length length to truncate to + * @param boolean $hover (optional) whether or not to add the rollover + * @return string truncate string + */ + public static function truncate($string, $length, $hover = true) + { + if (strlen($string) > $length) + { + if ($hover == true) + { + $string = '' . mb_strcut($string, 0, $length, 'UTF-8') . '…'; + } + else + { + $string = mb_strcut($string, 0, $length, 'UTF-8') . '…'; + } + } - return $string; - } + return $string; + } - // }}} - // {{{ Upper Words + // }}} + // {{{ Upper Words - /** - * Upper Words - * - * Applies strtolower() and ucwords() to the passed string. The - * exception being email addresses which are not formatted at all. - * - * @static - * @param string $string string to format - * @return string formatted string - */ - public static function upperWords($string) - { - // Only formats non-email addresses - if (filter_var($string, FILTER_VALIDATE_EMAIL) == false) - { - $string = ucwords(strtolower($string)); - } + /** + * Upper Words + * + * Applies strtolower() and ucwords() to the passed string. The + * exception being email addresses which are not formatted at all. + * + * @static + * @param string $string string to format + * @return string formatted string + */ + public static function upperWords($string) + { + // Only formats non-email addresses + if (filter_var($string, FILTER_VALIDATE_EMAIL) == false) + { + $string = ucwords(strtolower($string)); + } - return $string; - } + return $string; + } - // }}} + // }}} } -?> diff --git a/src/classes/Time.php b/src/classes/Time.php index e8ba3b6..1f7ca66 100644 --- a/src/classes/Time.php +++ b/src/classes/Time.php @@ -23,254 +23,253 @@ */ class Time { - // {{{ Intervals (in seconds) + // {{{ Intervals (in seconds) - /** - * Minute - * - * Seconds in a minute - * - * @var integer - */ - const MINUTE = 60; + /** + * Minute + * + * Seconds in a minute + * + * @var integer + */ + const MINUTE = 60; - /** - * Hour - * - * Seconds in an hour (minute * 60) - * - * @var integer - */ - const HOUR = 3600; + /** + * Hour + * + * Seconds in an hour (minute * 60) + * + * @var integer + */ + const HOUR = 3600; - /** - * Day - * - * Seconds in a day (hour * 24) - * - * @var integer - */ - const DAY = 86400; + /** + * Day + * + * Seconds in a day (hour * 24) + * + * @var integer + */ + const DAY = 86400; - /** - * Week - * - * Seconds in a week (day * 7) - * - * @var integer - */ - const WEEK = 604800; + /** + * Week + * + * Seconds in a week (day * 7) + * + * @var integer + */ + const WEEK = 604800; - /** - * Month - * - * Seconds in a month (day * 30) - * - * @var integer - */ - const MONTH = 2592000; + /** + * Month + * + * Seconds in a month (day * 30) + * + * @var integer + */ + const MONTH = 2592000; - /** - * Quarter - * - * Seconds in a quarter (day * 90) - * - * @var integer - */ - const QUARTER = 7776000; + /** + * Quarter + * + * Seconds in a quarter (day * 90) + * + * @var integer + */ + const QUARTER = 7776000; - /** - * Year - * - * Seconds in a year (day * 365) - * - * @var integer - */ - const YEAR = 31536000; + /** + * Year + * + * Seconds in a year (day * 365) + * + * @var integer + */ + const YEAR = 31536000; - /** - * Decade - * - * Seconds in a decade (year * 10) - * - * @var integer - */ - const DECADE = 315360000; + /** + * Decade + * + * Seconds in a decade (year * 10) + * + * @var integer + */ + const DECADE = 315360000; - /** - * Century - * - * Seconds in a decade (decade * 10) - * - * @var integer - */ - const CENTURY = 3153600000; + /** + * Century + * + * Seconds in a decade (decade * 10) + * + * @var integer + */ + const CENTURY = 3153600000; - // }}} + // }}} - /** - * Age - * - * Calculates age based on the passed date. - * - * @static - * @param string $date birth / inception date - * @return integer $age number of years old - * @todo Wondering if this really should live in the Date class since - * it's a Date function. Could flip the aliasing to preserve any - * older code. - */ - public static function age($date) - { - if (!preg_match('/\d{4}-\d{2}-\d{2}/', $date)) - { - $date = date('Y-m-d', strtotime($date)); - } + /** + * Age + * + * Calculates age based on the passed date. + * + * @static + * @param string $date birth / inception date + * @return integer $age number of years old + * @todo Wondering if this really should live in the Date class since + * it's a Date function. Could flip the aliasing to preserve any + * older code. + */ + public static function age($date) + { + if (!preg_match('/\d{4}-\d{2}-\d{2}/', $date)) + { + $date = date('Y-m-d', strtotime($date)); + } - list($year, $month, $day) = explode('-', $date, 3); + list($year, $month, $day) = explode('-', $date, 3); - $age = date('Y') - $year; + $age = date('Y') - $year; - if (date('md') < $month . $day) - { - $age--; - } + if (date('md') < $month . $day) + { + $age--; + } - return $age; - } + return $age; + } - /** - * Ago - * - * Generates a relative time (e.g. X minutes ago). - * - * @static - * @param mixed $time timestamp to calculate from - * @return string relative time - */ - public static function ago($time) - { - $current = strtotime(Time::timestamp()); - $time = preg_match('/^\d+$/', $time) ? $time : strtotime($time); + /** + * Ago + * + * Generates a relative time (e.g. X minutes ago). + * + * @static + * @param mixed $time timestamp to calculate from + * @return string relative time + */ + public static function ago($time) + { + $current = strtotime(Time::timestamp()); + $time = preg_match('/^\d+$/', $time) ? $time : strtotime($time); - if ($current == $time) - { - $time_ago = 'just now'; - } - else - { - if ($current > $time) - { - $difference = $current - $time; - $suffix = ' ago'; - } - else - { - $difference = $time - $current; - $suffix = ' from now'; - } + if ($current == $time) + { + $time_ago = 'just now'; + } + else + { + if ($current > $time) + { + $difference = $current - $time; + $suffix = ' ago'; + } + else + { + $difference = $time - $current; + $suffix = ' from now'; + } - // Less than 1 minute ago (seconds ago) - if ($difference < 60) - { - $time_ago = 'seconds'; - } - // Less than 1 hour ago (minutes ago) - elseif ($difference < Time::HOUR) - { - $minutes = round($difference / 60); + // Less than 1 minute ago (seconds ago) + if ($difference < 60) + { + $time_ago = 'seconds'; + } + // Less than 1 hour ago (minutes ago) + elseif ($difference < Time::HOUR) + { + $minutes = round($difference / 60); - if ($minutes == 60) - { - $time_ago = 'an hour'; - } - else - { - $time_ago = ($minutes == 1 ? 'a' : $minutes) . ' minute' . ($minutes != 1 ? 's' : ''); - } - } - // Less than 1 day ago (hours ago) - elseif ($difference < Time::DAY) - { - $hours = round($difference / Time::HOUR); + if ($minutes == 60) + { + $time_ago = 'an hour'; + } + else + { + $time_ago = ($minutes == 1 ? 'a' : $minutes) . ' minute' . ($minutes != 1 ? 's' : ''); + } + } + // Less than 1 day ago (hours ago) + elseif ($difference < Time::DAY) + { + $hours = round($difference / Time::HOUR); - if ($hours == 24) - { - $time_ago = 'a day'; - } - else - { - $time_ago = ($hours == 1 ? 'an' : $hours) . ' hour' . ($hours != 1 ? 's' : ''); - } - } - // Less than 1 week ago (days ago) - elseif ($difference < Time::WEEK) - { - $days = round($difference / Time::DAY); + if ($hours == 24) + { + $time_ago = 'a day'; + } + else + { + $time_ago = ($hours == 1 ? 'an' : $hours) . ' hour' . ($hours != 1 ? 's' : ''); + } + } + // Less than 1 week ago (days ago) + elseif ($difference < Time::WEEK) + { + $days = round($difference / Time::DAY); - if ($days == 7) - { - $time_ago = 'a week'; - } - else - { - $time_ago = ($days == 1 ? 'a' : $days) . ' day' . ($days != 1 ? 's' : ''); - } - } - // Less than 1 month ago (weeks ago) - elseif ($difference < Time::MONTH) - { - $weeks = round($difference / Time::WEEK); + if ($days == 7) + { + $time_ago = 'a week'; + } + else + { + $time_ago = ($days == 1 ? 'a' : $days) . ' day' . ($days != 1 ? 's' : ''); + } + } + // Less than 1 month ago (weeks ago) + elseif ($difference < Time::MONTH) + { + $weeks = round($difference / Time::WEEK); - if ($weeks == 4) - { - $time_ago = 'a month'; - } - else - { - $time_ago = ($weeks == 1 ? 'a' : $weeks) . ' week' . ($weeks != 1 ? 's' : ''); - } - } - // Less than 1 year ago (months ago) - elseif ($difference < Time::YEAR) - { - $months = round($difference / Time::MONTH); + if ($weeks == 4) + { + $time_ago = 'a month'; + } + else + { + $time_ago = ($weeks == 1 ? 'a' : $weeks) . ' week' . ($weeks != 1 ? 's' : ''); + } + } + // Less than 1 year ago (months ago) + elseif ($difference < Time::YEAR) + { + $months = round($difference / Time::MONTH); - if ($months == 12) - { - $time_ago = 'a year'; - } - else - { - $time_ago = ($months == 1 ? 'a' : $months) . ' month' . ($months != 1 ? 's' : ''); - } - } - // Over 1 year ago (years ago) - else - { - $years = round($difference / Time::YEAR); - $time_ago = ($years == 1 ? 'a' : $years) . ' year' . ($years != 1 ? 's' : ''); - } + if ($months == 12) + { + $time_ago = 'a year'; + } + else + { + $time_ago = ($months == 1 ? 'a' : $months) . ' month' . ($months != 1 ? 's' : ''); + } + } + // Over 1 year ago (years ago) + else + { + $years = round($difference / Time::YEAR); + $time_ago = ($years == 1 ? 'a' : $years) . ' year' . ($years != 1 ? 's' : ''); + } - $time_ago .= $suffix; - } + $time_ago .= $suffix; + } - return $time_ago; - } + return $time_ago; + } - /** - * Timestamp - * - * Current Universal Time in the specified format. - * - * @static - * @param string $format format of the timestamp - * @return string $timestamp formatted timestamp - */ - public static function timestamp($format = 'Y-m-d H:i:s') - { - return gmdate($format); - } + /** + * Timestamp + * + * Current Universal Time in the specified format. + * + * @static + * @param string $format format of the timestamp + * @return string $timestamp formatted timestamp + */ + public static function timestamp($format = 'Y-m-d H:i:s') + { + return gmdate($format); + } } -?> diff --git a/src/classes/Validate.php b/src/classes/Validate.php index 7567be8..2f613a3 100644 --- a/src/classes/Validate.php +++ b/src/classes/Validate.php @@ -24,153 +24,152 @@ */ class Validate { - /** - * Is Valid? - * - * Checks if a variable is valid based on the passed rules. - * - * @param mixed $value the value to be validated - * @param array $rules an array of rules (and messages) to validate with - * @return mixed boolean true if valid, array of errors if invalid - */ - public static function isValid($value, $rules) - { - $errors = []; + /** + * Is Valid? + * + * Checks if a variable is valid based on the passed rules. + * + * @param mixed $value the value to be validated + * @param array $rules an array of rules (and messages) to validate with + * @return mixed boolean true if valid, array of errors if invalid + */ + public static function isValid($value, $rules) + { + $errors = []; - if (is_array($rules)) - { - foreach ($rules as $rule => $message) - { - $rule = explode(':', $rule); + if (is_array($rules)) + { + foreach ($rules as $rule => $message) + { + $rule = explode(':', $rule); - switch (strtolower($rule[0])) - { - // @todo case 'alpha': - // @todo case 'alphanumeric': - // @todo case 'date': + switch (strtolower($rule[0])) + { + // @todo case 'alpha': + // @todo case 'alphanumeric': + // @todo case 'date': - // {{{ Checks using filter_var() + // {{{ Checks using filter_var() - case 'filter': - if (count($rule) < 2) - { - throw new Exception('Invalid validation rule, expected: "validate:boolean|email|float|int|ip|url".'); - } - else - { - switch (strtolower($rule[1])) - { - case 'boolean': - case 'email': - case 'float': - case 'int': - case 'ip': - case 'url': - $filter = constant('FILTER_VALIDATE_' . strtoupper($rule[1])); - break; + case 'filter': + if (count($rule) < 2) + { + throw new Exception('Invalid validation rule, expected: "validate:boolean|email|float|int|ip|url".'); + } + else + { + switch (strtolower($rule[1])) + { + case 'boolean': + case 'email': + case 'float': + case 'int': + case 'ip': + case 'url': + $filter = constant('FILTER_VALIDATE_' . strtoupper($rule[1])); + break; - default: - throw new Exception('Invalid filter, expecting boolean, email, float, int, ip or url.'); - break; - } + default: + throw new Exception('Invalid filter, expecting boolean, email, float, int, ip or url.'); + break; + } - if (!filter_var($value, $filter)) - { - $errors[] = $message; - } - } + if (!filter_var($value, $filter)) + { + $errors[] = $message; + } + } - break; + break; - // }}} - // {{{ Checks using strlen() + // }}} + // {{{ Checks using strlen() - case 'length': - if (count($rule) < 3) - { - throw new Exception('Invalid validation rule, expected: "length:<|<=|==|!=|>=|>:integer".'); - } - else - { - if (!filter_var($rule[2], FILTER_VALIDATE_INT)) - { - throw new Exception('Invalid length value, expecting an integer.'); - } - else - { - $length = strlen($value); + case 'length': + if (count($rule) < 3) + { + throw new Exception('Invalid validation rule, expected: "length:<|<=|==|!=|>=|>:integer".'); + } + else + { + if (!filter_var($rule[2], FILTER_VALIDATE_INT)) + { + throw new Exception('Invalid length value, expecting an integer.'); + } + else + { + $length = strlen($value); - switch ($rule[1]) - { - case '<': - $valid = $length < $rule[2]; - break; + switch ($rule[1]) + { + case '<': + $valid = $length < $rule[2]; + break; - case '<=': - $valid = $length <= $rule[2]; - break; + case '<=': + $valid = $length <= $rule[2]; + break; - case '==': - $valid = $length == $rule[2]; - break; + case '==': + $valid = $length == $rule[2]; + break; - case '!=': - $valid = $length != $rule[2]; - break; + case '!=': + $valid = $length != $rule[2]; + break; - case '>=': - $valid = $length >= $rule[2]; - break; + case '>=': + $valid = $length >= $rule[2]; + break; - case '>': - $valid = $length > $rule[2]; - break; + case '>': + $valid = $length > $rule[2]; + break; - default: - throw new Exception('Invalid operator, expecting <, <=, ==, !=, >= or >.'); - break; - } + default: + throw new Exception('Invalid operator, expecting <, <=, ==, !=, >= or >.'); + break; + } - if (!$valid) - { - $errors[] = $message; - } - } - } + if (!$valid) + { + $errors[] = $message; + } + } + } - break; + break; - // }}} + // }}} - // @todo case 'range': + // @todo case 'range': - // {{{ Checks using preg_match() + // {{{ Checks using preg_match() - case 'regex': - if (count($rule) < 3) - { - throw new Exception('Invalid validation rule, expected: "regex:is|not:string".'); - } - else - { - $rule[1] = strtolower($rule[1]); + case 'regex': + if (count($rule) < 3) + { + throw new Exception('Invalid validation rule, expected: "regex:is|not:string".'); + } + else + { + $rule[1] = strtolower($rule[1]); - if (($rule[1] == 'is' && preg_match($rule[2], $value)) - || ($rule[1] == 'not' && !preg_match($rule[2], $value))) - { - $errors[] = $message; - } - } - break; + if (($rule[1] == 'is' && preg_match($rule[2], $value)) + || ($rule[1] == 'not' && !preg_match($rule[2], $value))) + { + $errors[] = $message; + } + } + break; - // }}} - } + // }}} + } - } - } + } + } - return count($errors) ? $errors : true; - } + return count($errors) ? $errors : true; + } } -?> diff --git a/src/pickles.php b/src/pickles.php index a77769a..52a8b73 100644 --- a/src/pickles.php +++ b/src/pickles.php @@ -26,20 +26,20 @@ // @todo Finish reworking constants to be part of the Config object if (!defined('SITE_PATH')) { - // Establishes our site paths, sanity check is to allow vfsStream in our tests - define('SITE_PATH', getcwd() . '/../'); + // Establishes our site paths, sanity check is to allow vfsStream in our tests + define('SITE_PATH', getcwd() . '/../'); } if (!defined('SITE_CLASS_PATH')) { - define('SITE_CLASS_PATH', SITE_PATH . 'classes/'); - define('SITE_MODEL_PATH', SITE_PATH . 'models/'); - // @todo The following 2 constants are being used in sites will need to update them before removing - define('SITE_MODULE_PATH', SITE_PATH . 'modules/'); - define('SITE_TEMPLATE_PATH', SITE_PATH . 'templates/'); + define('SITE_CLASS_PATH', SITE_PATH . 'classes/'); + define('SITE_MODEL_PATH', SITE_PATH . 'models/'); + // @todo The following 2 constants are being used in sites will need to update them before removing + define('SITE_MODULE_PATH', SITE_PATH . 'modules/'); + define('SITE_TEMPLATE_PATH', SITE_PATH . 'templates/'); - define('PRIVATE_PATH', SITE_PATH . 'private/'); - define('LOG_PATH', PRIVATE_PATH . 'logs/'); + define('PRIVATE_PATH', SITE_PATH . 'private/'); + define('LOG_PATH', PRIVATE_PATH . 'logs/'); } // }}} @@ -52,7 +52,7 @@ error_reporting(-1); // Defaults timezone to UTC if not set if (ini_get('date.timezone') == '') { - ini_set('date.timezone', 'Etc/UTC'); + ini_set('date.timezone', 'Etc/UTC'); } // Sets the session variables @@ -78,38 +78,38 @@ ini_set('session.hash_function', 1); */ function __autoload($class) { - $loaded = false; - $filename = preg_replace('/_/', '/', $class) . '.php'; + $loaded = false; + $filename = preg_replace('/_/', '/', $class) . '.php'; - $pickles_path = dirname(__FILE__) . '/'; - $pickles_paths = [ - 'class' => $pickles_path . 'classes/', - ]; + $pickles_path = dirname(__FILE__) . '/'; + $pickles_paths = [ + 'class' => $pickles_path . 'classes/', + ]; - // Path as the key, boolean value is whether ot not to convert back to hyphenated - $paths = [ - $pickles_paths['class'] => false, - SITE_CLASS_PATH => false, - SITE_MODEL_PATH => false, - SITE_MODULE_PATH => true, - ]; + // Path as the key, boolean value is whether ot not to convert back to hyphenated + $paths = [ + $pickles_paths['class'] => false, + SITE_CLASS_PATH => false, + SITE_MODEL_PATH => false, + SITE_MODULE_PATH => true, + ]; - foreach ($paths as $path => $hyphenated) - { - // Converts the filename back to hypenated - if ($hyphenated == true) - { - $filename = strtolower(preg_replace('/([A-Z]{1})/', '-$1', $filename));; - } + foreach ($paths as $path => $hyphenated) + { + // Converts the filename back to hypenated + if ($hyphenated == true) + { + $filename = strtolower(preg_replace('/([A-Z]{1})/', '-$1', $filename));; + } - if (file_exists($path . $filename)) - { - $loaded = require_once $path . $filename; - break; - } - } + if (file_exists($path . $filename)) + { + $loaded = require_once $path . $filename; + break; + } + } - return $loaded; + return $loaded; } spl_autoload_register('__autoload'); @@ -129,28 +129,28 @@ require_once $config->pickles['path'] . '../vendor/autoload.php'; // Configures any available PHP configuration options if (is_array($config->php) && count($config->php)) { - foreach ($config->php as $variable => $value) - { - ini_set($variable, $value); - } + foreach ($config->php as $variable => $value) + { + ini_set($variable, $value); + } } // Starts session handling (old) if (isset($config->pickles['session'])) { - if (session_id() == '' && $config->pickles['session'] !== false) - { - new Session(); - } + if (session_id() == '' && $config->pickles['session'] !== false) + { + new Session(); + } } // Starts session handling (new) if (isset($config->pickles['sessions'])) { - if (session_id() == '' && $config->pickles['sessions'] !== false) - { - new Session(); - } + if (session_id() == '' && $config->pickles['sessions'] !== false) + { + new Session(); + } } // }}} @@ -158,9 +158,8 @@ if (isset($config->pickles['sessions'])) if (!isset($_REQUEST['request'])) { - $_REQUEST['request'] = 'home'; + $_REQUEST['request'] = 'home'; } // }}} -?> diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b9d94c5..4f614a2 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -11,26 +11,26 @@ $root = org\bovigo\vfs\vfsStream::setup('site'); if (!defined('SITE_PATH')) { - define('SECURITY_LEVEL_USER', 10); - define('SECURITY_LEVEL_ADMIN', 20); - define('SITE_PATH', org\bovigo\vfs\vfsStream::url('site/')); + define('SECURITY_LEVEL_USER', 10); + define('SECURITY_LEVEL_ADMIN', 20); + define('SITE_PATH', org\bovigo\vfs\vfsStream::url('site/')); } require_once 'src/pickles.php'; if (!file_exists(SITE_MODULE_PATH)) { - mkdir(SITE_MODULE_PATH, 0644); + mkdir(SITE_MODULE_PATH, 0644); } if (!file_exists(SITE_TEMPLATE_PATH)) { - mkdir(SITE_TEMPLATE_PATH, 0644); + mkdir(SITE_TEMPLATE_PATH, 0644); } if (!file_exists(SITE_TEMPLATE_PATH . '__shared/')) { - mkdir(SITE_TEMPLATE_PATH . '__shared/', 0644); + mkdir(SITE_TEMPLATE_PATH . '__shared/', 0644); } $_SERVER['HTTP_HOST'] = 'testsite.com'; @@ -39,17 +39,17 @@ $_SERVER['SERVER_ADDR'] = '127.0.0.1'; function setUpRequest($request, $method = 'GET') { - $_SERVER['REQUEST_URI'] = '/' . $request; - $_SERVER['REQUEST_METHOD'] = $method; - $_REQUEST['request'] = $request; + $_SERVER['REQUEST_URI'] = '/' . $request; + $_SERVER['REQUEST_METHOD'] = $method; + $_REQUEST['request'] = $request; } function setUpConfig($config) { - file_put_contents( - SITE_PATH . 'config.php', - '' - ); + file_put_contents( + SITE_PATH . 'config.php', + '' + ); } `mysql -e 'TRUNCATE TABLE test.pickles;'`; @@ -57,4 +57,3 @@ function setUpConfig($config) `mysql -e 'TRUNCATE TABLE test.users;'`; `echo 'flush_all' | nc localhost 11211`; -?> diff --git a/tests/classes/API/AYAHTest.php b/tests/classes/API/AYAHTest.php index 7502337..8fd1ac6 100644 --- a/tests/classes/API/AYAHTest.php +++ b/tests/classes/API/AYAHTest.php @@ -2,40 +2,39 @@ class API_AYAHTest extends PHPUnit_Framework_TestCase { - /** - * @expectedException Exception - * @expectedExceptionMessage Missing API configuration - */ - public function testGetHTMLMissingConfig() - { - API_AYAH::getHTML(); - } + /** + * @expectedException Exception + * @expectedExceptionMessage Missing API configuration + */ + public function testGetHTMLMissingConfig() + { + API_AYAH::getHTML(); + } - /** - * @expectedException Exception - * @expectedExceptionMessage Missing API configuration - */ - public function testIsHumanMissingConfig() - { - API_AYAH::isHuman(); - } + /** + * @expectedException Exception + * @expectedExceptionMessage Missing API configuration + */ + public function testIsHumanMissingConfig() + { + API_AYAH::isHuman(); + } - public function testGetHTML() - { - $config = Config::getInstance(); - $config->data['api']['ayah'] = [ - 'publisher_key' => '01f70454bada303692be5f36a8fd104eba8b00dd', - 'scoring_key' => '80cc3f9c6e1da29369c238d55bd8528a968473ad', - ]; + public function testGetHTML() + { + $config = Config::getInstance(); + $config->data['api']['ayah'] = [ + 'publisher_key' => '01f70454bada303692be5f36a8fd104eba8b00dd', + 'scoring_key' => '80cc3f9c6e1da29369c238d55bd8528a968473ad', + ]; - $this->assertRegExp('/
<\/div>