1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
<?php
namespace oroboros\core;
/*
* The MIT License
*
* Copyright 2016 Brian Dayhoff <brian@mopsyd.me>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* <Oroboros Common Library>
* @review whether or not this file is neccessary any longer. The legacy build did not use composer and needed some checking functionality, but this package does not. This requirement may return when composer is factored back out, but it can be dealt with smarter than procedural code sets, even if they are namespaced
* A library of common functions
* and utilities to make life easier.
*/
/**
* <Require Classes and Functional Declaration Files Safely>
* Safely requires a file that should only be included once. If already loaded,
* this function will simply return false. If file does not exist, will throw an
* exception instead of an error, making it catcheable even if error mode is not
* set to exception.
* @since 0.0.1a
* @param string $filename The name of the file to load.
* @return boolean Returns [TRUE] if successfully loaded, [FALSE] if already loaded.
* @throws \oroboros\core\utilities\exception\Exception If file does not exist, or is not readable.
*/
function require_safely($filename) {
//make real system path, to check against relative links
$file = realpath($filename);
if (is_readable($file)) {
if (!in_array($file, get_included_files())) {
require_once $file;
return TRUE;
}
return TRUE;
}
throw new \oroboros\core\utilities\exception\Exception("[ " . (string) $filename
. " ] not found or not readable.", interfaces\api\ExceptionCodeApi::ERROR_CORE);
}
/**
* <Oroboros Routine Dispatch>
* Runs a valid procedural routine within the Oroboros core system.
* Does not return any output. If the routine is not valid, throws
* an Exception. If the routine runs, but produces an
* exception or error, it will be caught and replaced with an
* \OroborosRoutineException, providing the original exception
* as the third parameter.
* @see \oroboros\core\utilities\exception\Exception
* @see \oroboros\core\utilities\exception\OroborosRuntimeException
* @param type $routine
* @param type $safemode
* @return boolean
* @throws \oroboros\core\utilities\exception\Exception
* @throws \oroboros\core\utilities\exception\OroborosRoutineException
* @since 0.0.1a
*/
function oroboros_run_routine($routine, array $params = array(), array $flags = array()) {
$safemode = ((isset($flags['safemode']) ? $flags['safemode'] : FALSE));
try {
$file = realpath(OROBOROS_SRC . 'routines' . DIRECTORY_SEPARATOR
. strtolower($routine) . '.routine.php');
$file = ((is_readable($file)) ? $file : FALSE);
if ($file && $safemode) {
require_safely($file);
return (!in_array($file, get_included_files()) ? TRUE : FALSE);
} elseif ($file && !$safemode) {
require $file;
} else {
throw new \oroboros\core\utilities\exception\Exception("Routine ["
. (string) $routine
. '] could not be loaded!', \oroboros\core\api\ExceptionCodeApi::ERROR_ROUTINE);
return TRUE;
}
return TRUE;
} catch (\Exception $e) {
//routine not found
if (($e instanceof \oroboros\core\utilities\exception\Exception) && $e->getCode() === \oroboros\core\interfaces\api\ExceptionCodeApi::ERROR_ROUTINE) {
throw new \oroboros\core\utilities\exception\Exception("Invalid routine specified: ["
. (string) $routine . "]", 0, $e);
} else {
//routine generated an error or threw an exception
throw new \oroboros\core\utilities\exception\OroborosRoutineException("Error during execution "
. "of routine [" . $routine . ']' . PHP_EOL . '>'
. $e->getMessage(), $e->getCode(), $e);
}
}
}
/**
* <Check if Running from Command Line>
* It is common for scripts to crash if the wrong output headers
* are sent when a script runs from the command line. This function
* will return a simple boolean, allowing you to easily check for this.
* @return boolean TRUE if cli, FALSE if not cli
*/
function is_cli() {
return (PHP_SAPI == 'cli' ? TRUE : FALSE);
}
/**
* <Check if Request is from AJAX>
* In order for the system to bootstrap the same way for both page
* and ajax requests, there needs to be a switch to determine which
* kind of request it is, so the correct controller can be loaded
* to handle the request. Oroboros uses the standard HTTP ajax header:
* X-Requested-With=XMLHttpRequest.
*
* This function will check if that header was sent to the system,
* and load an ajax controller if so.
* @note This header is not universal despite being mostly standardized, and can also be spoofed. Do no only check for this, use other authentication also.
* @return boolean TRUE if ajax, FALSE if not ajax
*/
function is_ajax() {
$headers = request_headers();
return ($headers && \array_key_exists('X-Requested-With', $headers) && (\strtoupper($headers['X-Requested-With']) === 'XMLHTTPREQUEST'));
}
function request_headers() {
$response = FALSE;
if (!is_cli()) {
if (function_exists("\\apache_request_headers")) {
$response = \apache_request_headers();
}
}
return $response;
}
/**
* <Convert Oroboros Core Filepath to Namespaced Classname>
* This will only work on files within the oroboros directory.
* Returns [false] if either of: File not found OR outside of oroboros directory.
* @note This function does not do any explicit checking to insure the actual filepath contains a class, it only produces a valid system namespaced classpath for a class that would be in that file. Inproper usage may cause logic errors.
* @param string $classFilepath a valid file path to a class file
* @return boolean|string
*/
function oroboros_classfile_to_classname($classFilepath = FALSE) {
if (!$classFilepath || (!(is_string($classFilepath) && is_readable($classFilepath)))) {
return FALSE;
}
//get class name
$classfileIndex = explode(DIRECTORY_SEPARATOR, $classFilepath);
$classfileName = array_pop($classfileIndex);
$classname = array_shift(explode('.', $classfileName));
//get namespace
while (!empty($classFilepath) && array_shift($classfileIndex) !== "oroboros") {
}
//If the array is empty, the class is not in the oroboros hierarchy
if (empty($classfileIndex)) {
return FALSE;
}
return '\\oroboros\\' . implode('\\', $classfileIndex) . '\\' . $classfileName;
}
/**
* <Localize Path to URL>
* This will return a URL based on the current
* hostname, relative to the Oroboros Core base.
* @param string $path
* @return string
*/
function localize_url($path) {
return str_replace('\\', '/', str_replace(\oroboros\Oroboros::OROBOROS_BASEPATH, OROBOROS_URL . '/oroboros', $path));
}