Created
February 29, 2016 05:01
-
-
Save shgysk8zer0/83acffd6d7ace647ba6a to your computer and use it in GitHub Desktop.
NamespacedFunctions.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @author Chris Zuber | |
* @copyright 2016, Chris Zuber | |
* @license http://opensource.org/licenses/GPL-3.0 GNU General Public License, version 3 (GPL-3.0) | |
* This program is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU General Public License | |
* as published by the Free Software Foundation, either version 3 | |
* of the License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
/** | |
* An Object-Oriented autoloader for namespaced functions that functions similarly | |
* to `spl_autoload` in that it converts namespaces to lower case paths, automatically | |
* adding ".php" extension, and loads this from the include path. | |
* | |
* @example NamespacedFunction::load('\Namespace')->function($args...); | |
* @example NamespacedFunction::{'\Namespace\Function'}($args...); | |
* @example call_user_func(['NamespacedFunction', '\Namespace\Function'], $arg[1]...); | |
* | |
* Where all example perform: | |
* `require_once "$namespace.php"`; | |
* `\$namespace\$function($args[1], ...)` | |
*/ | |
final class NamespacedFunction | |
{ | |
const NS = '\\'; | |
private static $_instances = array(); | |
/** | |
* The given namespace | |
* @var string | |
*/ | |
private $_namespace = ''; | |
/** | |
* The file path as converted from the namespace | |
* @var string | |
*/ | |
private $_path = ''; | |
/** | |
* Create an instance and load the file, if required | |
* | |
* @param string $namespace The file's namespace which must relate to its path | |
*/ | |
public function __construct($namespace) | |
{ | |
$this->_escaped_ns = preg_quote(self::NS, '/'); | |
$this->_normalizeNS($namespace); | |
$this->_namespace = $namespace; | |
$this->_path = $this->_getPath($namespace); | |
if (file_exists($this->_path)) { | |
include_once $this->_path; | |
} else { | |
throw new \Exception(sprintf('"%s": failed to open stream: No such file or directory', $this->_path)); | |
} | |
} | |
/** | |
* Get the callalble, namespaced function name as a string | |
* | |
* @param string $function The name of the function | |
* @return callalble The function name with namespace | |
*/ | |
public function __get($function) | |
{ | |
return $this . self::NS . $function; | |
} | |
/** | |
* Calls a function from within the namespaced PHP script | |
* | |
* @param string $function The function to call | |
* @param array $args Array of arguments to pass to it | |
* @return mixed The return of the funciton | |
*/ | |
public function __call($function, Array $args = array()) | |
{ | |
if ($this->__isset($function)) { | |
return call_user_func_array($this->__get($function), $args); | |
} else { | |
throw new \Exception(sprintf("function '%s' not found or invalid function name in script '%s'", $function, $this->_path)); | |
} | |
} | |
/** | |
* Returns true if function exists in script | |
* | |
* @param string $function Name of function | |
* @return boolean If it exists in the script/namespace | |
*/ | |
public function __isset($function) | |
{ | |
return function_exists($this->__get($function)); | |
} | |
/** | |
* Returns the namespace of the loaded script | |
* | |
* @return string Namespace | |
*/ | |
public function __toString() | |
{ | |
return $this->_namespace; | |
} | |
public static function load($namespace) | |
{ | |
if (! array_key_exists($namespace, static::$_instances)) { | |
static::$_instances[$namespace] = new self($namespace); | |
} | |
return static::$_instances[$namespace]; | |
} | |
/** | |
* Static method to call functions from namespaced scripts, loading file if necessary | |
* | |
* @param string $namespace_func `\Namespace\Function` | |
* @param Array $args Array of arguments to pass | |
* @return mixed The return of the function | |
*/ | |
public static function __callStatic($namespace_func, Array $args) | |
{ | |
$namespace = explode(self::NS, $namespace_func); | |
$function = array_pop($namespace); | |
$namespace = join(self::NS, $namespace); | |
return static::load($namespace)->__call($function, $args); | |
} | |
/** | |
* Returns the absolute path converted from namespace, based on `DOCUMENT_ROOT` | |
* @param string $namespace The namespace to use {\Namespace} | |
* @return string The converted path {/abs_path/to/namespace.php} | |
*/ | |
private function _getPath($namespace) | |
{ | |
$namespace = trim($namespace, self::NS); | |
$script = strtolower(str_replace(self::NS, '/', $namespace)); | |
if (! pathinfo($script, PATHINFO_EXTENSION)) { | |
$script .= '.php'; | |
} | |
return $script; | |
} | |
/** | |
* Handles inconsistencies in namespaces, such as whether or not it begins with "\" | |
* | |
* @param string $namespace The given namespace by reference | |
* @return void | |
*/ | |
private function _normalizeNS(&$namespace) | |
{ | |
$namespace = self::NS . trim($namespace, self::NS); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A PHP class for converting function libraries (with namespace) into class-like objects
Where all example perform: