PHP Classes

File: src/Request/Support/CallableRegistry.php

Recommend this page to a friend!
  Classes of Thierry Feuzeu   Jaxon   src/Request/Support/CallableRegistry.php   Download  
File: src/Request/Support/CallableRegistry.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Jaxon
Call PHP classes from JavaScript using AJAX
Author: By
Last change:
Date: 4 years ago
Size: 10,379 bytes
 

Contents

Class file image Download
<?php /** * CallableRegistry.php - Jaxon callable object registrar * * This class is the entry point for class, directory and namespace registration. * * @package jaxon-core * @author Thierry Feuzeu <thierry.feuzeu@gmail.com> * @copyright 2019 Thierry Feuzeu <thierry.feuzeu@gmail.com> * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License * @link https://github.com/jaxon-php/jaxon-core */ namespace Jaxon\Request\Support; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; class CallableRegistry { /** * The callable repository * * @var CallableRepository */ public $xRepository; /** * The registered directories * * These are directories registered without a namespace. * * @var array */ protected $aDirectories = []; /** * Indicate if the registered directories are already parsed * * @var boolean */ protected $bParsedDirectories = false; /** * The registered namespaces * * These are the namespaces specified when registering directories. * * @var array */ protected $aNamespaces = []; /** * Indicate if the registered namespaces are already parsed * * @var boolean */ protected $bParsedNamespaces = false; /** * If the underscore is used as separator in js class names. * * @var boolean */ protected $bUsingUnderscore = false; /** * The Composer autoloader * * @var Autoloader */ private $xAutoloader = null; /** * The class constructor * * @param CallableRepository $xRepository */ public function __construct(CallableRepository $xRepository) { $this->xRepository = $xRepository; // Set the composer autoloader $sAutoloadFile = __DIR__ . '/../../../../../autoload.php'; if(file_exists($sAutoloadFile)) { $this->xAutoloader = require($sAutoloadFile); } } /** * * @param string $sDirectory The directory being registered * @param array $aOptions The associated options * * @return void */ public function addDirectory($sDirectory, array $aOptions) { // Set the autoload option default value if(!key_exists('autoload', $aOptions)) { $aOptions['autoload'] = true; } $this->aDirectories[$sDirectory] = $aOptions; } /** * * @param string $sNamespace The namespace of the directory being registered * @param array $aOptions The associated options * * @return void */ public function addNamespace($sNamespace, array $aOptions) { // Separator default value if(!key_exists('separator', $aOptions)) { $aOptions['separator'] = '.'; } $aOptions['separator'] = trim($aOptions['separator']); if(!in_array($aOptions['separator'], ['.', '_'])) { $aOptions['separator'] = '.'; } if($aOptions['separator'] == '_') { $this->bUsingUnderscore = true; } // Set the autoload option default value if(!key_exists('autoload', $aOptions)) { $aOptions['autoload'] = true; } // Register the dir with PSR4 autoloading if(($aOptions['autoload']) && $this->xAutoloader != null) { $this->xAutoloader->setPsr4($sNamespace . '\\', $aOptions['directory']); } $this->aNamespaces[$sNamespace] = $aOptions; } /** * Read classes from registered directories (without namespaces) * * @return void */ protected function parseDirectories() { // Browse directories without namespaces and read all the files. // This is to be done only once. if($this->bParsedDirectories) { return; } $this->bParsedDirectories = true; foreach($this->aDirectories as $sDirectory => $aOptions) { $itFile = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sDirectory)); // Iterate on dir content foreach($itFile as $xFile) { // skip everything except PHP files if(!$xFile->isFile() || $xFile->getExtension() != 'php') { continue; } $sClassName = $xFile->getBasename('.php'); $aClassOptions = ['timestamp' => $xFile->getMTime()]; // No more classmap autoloading. The file will be included when needed. if(($aOptions['autoload'])) { $aClassOptions['include'] = $xFile->getPathname(); } $this->xRepository->addClass($sClassName, $aClassOptions, $aOptions); } } } /** * Read classes from registered directories (with namespaces) * * @return void */ protected function parseNamespaces() { // Browse directories with namespaces and read all the files. // This is to be done only once. if($this->bParsedNamespaces) { return; } $this->bParsedNamespaces = true; $sDS = DIRECTORY_SEPARATOR; foreach($this->aNamespaces as $sNamespace => $aOptions) { $this->xRepository->addNamespace($sNamespace, ['separator' => $aOptions['separator']]); // Iterate on dir content $sDirectory = $aOptions['directory']; $itFile = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sDirectory)); foreach($itFile as $xFile) { // skip everything except PHP files if(!$xFile->isFile() || $xFile->getExtension() != 'php') { continue; } // Find the class path (the same as the class namespace) $sClassPath = $sNamespace; $sRelativePath = substr($xFile->getPath(), strlen($sDirectory)); $sRelativePath = trim(str_replace($sDS, '\\', $sRelativePath), '\\'); if($sRelativePath != '') { $sClassPath .= '\\' . $sRelativePath; } $this->xRepository->addNamespace($sClassPath, ['separator' => $aOptions['separator']]); $sClassName = $sClassPath . '\\' . $xFile->getBasename('.php'); $aClassOptions = ['namespace' => $sNamespace, 'timestamp' => $xFile->getMTime()]; $this->xRepository->addClass($sClassName, $aClassOptions, $aOptions); } } } /** * Find options for a class which is registered with namespace * * @param string $sClassName The class name * * @return array|null */ protected function getClassOptionsFromNamespaces($sClassName) { // Find the corresponding namespace $sNamespace = null; foreach(array_keys($this->aNamespaces) as $_sNamespace) { if(substr($sClassName, 0, strlen($_sNamespace) + 1) == $_sNamespace . '\\') { $sNamespace = $_sNamespace; break; } } if($sNamespace === null) { return null; // Class not registered } // Get the class options $aOptions = $this->aNamespaces[$sNamespace]; $aClassOptions = ['namespace' => $sNamespace]; return $this->xRepository->makeClassOptions($sClassName, $aClassOptions, $aOptions); } /** * Find the options associated with a registered class name * * @param string $sClassName The class name * * @return array|null */ protected function getClassOptions($sClassName) { // Find options for a class registered with namespace. $aOptions = $this->getClassOptionsFromNamespaces($sClassName); if($aOptions !== null) { return $aOptions; } // Without a namespace, we need to parse all classes to be able to find one. $this->parseDirectories(); // Find options for a class registered without namespace. return $this->xRepository->getClassOptions($sClassName); } /** * Find a callable object by class name * * @param string $sClassName The class name of the callable object * * @return CallableObject */ public function getCallableObject($sClassName) { // Replace all separators ('.' and '_') with antislashes, and remove the antislashes // at the beginning and the end of the class name. $sClassName = (string)$sClassName; $sClassName = trim(str_replace('.', '\\', $sClassName), '\\'); if($this->bUsingUnderscore) { $sClassName = trim(str_replace('_', '\\', $sClassName), '\\'); } // Check if the callable object was already created. if(($xCallableObject = $this->xRepository->getCallableObject($sClassName)) != null) { return $xCallableObject; } $aOptions = $this->getClassOptions($sClassName); if($aOptions === null) { return null; } return $this->xRepository->createCallableObject($sClassName, $aOptions); } /** * Create callable objects for all registered classes * * @return void */ public function createCallableClasses() { $this->parseDirectories(); $this->parseNamespaces(); } /** * Create callable objects for all registered classes * * @return void */ public function createCallableObjects() { $this->createCallableClasses(); foreach($this->xRepository->getClasses() as $sClassName => $aClassOptions) { // Make sure we create each callable object only once. if(!$this->xRepository->getCallableObject($sClassName)) { $this->xRepository->createCallableObject($sClassName, $aClassOptions); } } } }