mirror of
https://github.com/typemill/typemill.git
synced 2025-10-17 23:56:09 +02:00
Version 1.0.0
This commit is contained in:
23
system/Controllers/Controller.php
Normal file
23
system/Controllers/Controller.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace System\Controllers;
|
||||
|
||||
/* Use the slim-container */
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
protected $c;
|
||||
|
||||
public function __construct(ContainerInterface $c)
|
||||
{
|
||||
$this->c = $c;
|
||||
}
|
||||
|
||||
protected function render404($response, $content = NULL)
|
||||
{
|
||||
return $this->c->view->render($response->withStatus(404), '/404.twig', $content);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
132
system/Controllers/PageController.php
Normal file
132
system/Controllers/PageController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace System\Controllers;
|
||||
|
||||
use System\Models\Folder;
|
||||
use System\Models\Cache;
|
||||
use System\Models\Helpers;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
|
||||
public function index($request, $response, $args)
|
||||
{
|
||||
|
||||
/* Initiate Variables */
|
||||
$structure = false;
|
||||
$contentHTML = false;
|
||||
$item = false;
|
||||
$breadcrumb = false;
|
||||
$description = '';
|
||||
$settings = $this->c->get('settings');
|
||||
$pathToContent = $settings['rootPath'] . $settings['contentFolder'];
|
||||
$cache = new Cache();
|
||||
$uri = $request->getUri();
|
||||
$base_url = $uri->getBaseUrl();
|
||||
|
||||
if($cache->validate())
|
||||
{
|
||||
$structure = $this->getCachedStructure($cache);
|
||||
$cached = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$structure = $this->getFreshStructure($pathToContent, $cache, $uri);
|
||||
$cached = false;
|
||||
|
||||
if(!$structure)
|
||||
{
|
||||
$content = '<h1>No Content</h1><p>Your content folder is empty.</p>';
|
||||
$this->c->view->render($response, '/index.twig', [ 'content' => $content ]);
|
||||
}
|
||||
}
|
||||
|
||||
/* if the user is on startpage */
|
||||
if(empty($args))
|
||||
{
|
||||
/* check, if there is an index-file in the root of the content folder */
|
||||
$contentMD = file_exists($pathToContent . DIRECTORY_SEPARATOR . 'index.md') ? file_get_contents($pathToContent . DIRECTORY_SEPARATOR . 'index.md') : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get the request url */
|
||||
$urlRel = $uri->getBasePath() . '/' . $args['params'];
|
||||
|
||||
/* find the url in the content-item-tree and return the item-object for the file */
|
||||
$item = Folder::getItemForUrl($structure, $urlRel);
|
||||
|
||||
if(!$item && $cached)
|
||||
{
|
||||
$structure = $this->getFreshStructure($pathToContent, $cache, $uri);
|
||||
$item = Folder::getItemForUrl($structure, $urlRel);
|
||||
}
|
||||
if(!$item){ return $this->render404($response, array( 'navigation' => $structure, 'settings' => $settings, 'base_url' => $base_url )); }
|
||||
|
||||
/* get breadcrumb for page */
|
||||
$breadcrumb = Folder::getBreadcrumb($structure, $item->keyPathArray);
|
||||
|
||||
/* add the paging to the item */
|
||||
$item = Folder::getPagingForItem($structure, $item);
|
||||
|
||||
/* check if url is a folder. If so, check if there is an index-file for the folder */
|
||||
if($item->elementType == 'folder' && $item->index)
|
||||
{
|
||||
$filePath = $pathToContent . $item->path . DIRECTORY_SEPARATOR . 'index.md';
|
||||
}
|
||||
elseif($item->elementType == 'file')
|
||||
{
|
||||
$filePath = $pathToContent . $item->path;
|
||||
}
|
||||
|
||||
/* read the content of the file */
|
||||
$contentMD = isset($filePath) ? file_get_contents($filePath) : false;
|
||||
}
|
||||
|
||||
/* initialize parsedown */
|
||||
$Parsedown = new \ParsedownExtra();
|
||||
|
||||
/* parse markdown-file to html-string */
|
||||
$contentHTML = $Parsedown->text($contentMD);
|
||||
$description = substr(strip_tags($contentHTML),0,150);
|
||||
$description = trim(preg_replace('/\s+/', ' ', $description));
|
||||
|
||||
/*
|
||||
$timer['topiccontroller']=microtime(true);
|
||||
$timer['end topiccontroller']=microtime(true);
|
||||
Helpers::printTimer($timer);
|
||||
*/
|
||||
|
||||
$route = empty($args) && $settings['startpage'] ? '/cover.twig' : '/index.twig';
|
||||
|
||||
$this->c->view->render($response, $route, array('navigation' => $structure, 'content' => $contentHTML, 'item' => $item, 'breadcrumb' => $breadcrumb, 'settings' => $settings, 'description' => $description, 'base_url' => $base_url ));
|
||||
}
|
||||
|
||||
|
||||
protected function getCachedStructure($cache)
|
||||
{
|
||||
return $cache->getData('structure');
|
||||
}
|
||||
|
||||
|
||||
protected function getFreshStructure($pathToContent, $cache, $uri)
|
||||
{
|
||||
/* scan the content of the folder */
|
||||
$structure = Folder::scanFolder($pathToContent);
|
||||
|
||||
/* if there is no content, render an empty page */
|
||||
if(count($structure) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* create an array of object with the whole content of the folder */
|
||||
$structure = Folder::getFolderContentDetails($structure, $uri->getBaseUrl(), $uri->getBasePath());
|
||||
|
||||
/* cache navigation */
|
||||
$cache->refresh($structure, 'structure');
|
||||
|
||||
return $structure;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
138
system/Controllers/SetupController.php
Normal file
138
system/Controllers/SetupController.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace System\Controllers;
|
||||
|
||||
use \Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class SetupController extends Controller
|
||||
{
|
||||
public function setup($request, $response, $args)
|
||||
{
|
||||
$themes = $this->getThemes();
|
||||
$copyright = $this->getCopyright();
|
||||
$uri = $request->getUri();
|
||||
$base_url = $uri->getBaseUrl();
|
||||
$errors = false;
|
||||
|
||||
/* Check, if setting folder is */
|
||||
if(!is_writable($this->c->get('settings')['settingsPath'])){ $errors['folder'] = 'Your settings folder is not writable.'; }
|
||||
|
||||
$data = array(
|
||||
'themes' => $themes,
|
||||
'copyright' => $copyright,
|
||||
'inputs' => false,
|
||||
'errors' => $errors,
|
||||
'base_url' => $base_url
|
||||
);
|
||||
$this->c->view->render($response, '/setup.twig', $data);
|
||||
}
|
||||
|
||||
public function save($request, $response, $args)
|
||||
{
|
||||
if($request->isPost())
|
||||
{
|
||||
$params = $request->getParams();
|
||||
|
||||
$copyright = $this->getCopyright();
|
||||
$themes = $this->getThemes();
|
||||
$errors = array();
|
||||
$uri = $request->getUri();
|
||||
$base_url = $uri->getBaseUrl();
|
||||
|
||||
/* Validate Title */
|
||||
if(!isset($params['title'])){ $errors['title'] = 'Please add a title. '; }
|
||||
if(strlen($params['title']) < 2){ $errors['title'] = 'Title is too short (< 2). '; }
|
||||
if(strlen($params['title']) > 20){ $errors['title'] = 'Title is too long (> 20). '; }
|
||||
|
||||
/* Validate Author */
|
||||
if(isset($params['author']) && !empty($params['author']))
|
||||
{
|
||||
if(strlen($params['author']) < 2){ $errors['author'] = 'Text is too short (< 2). '; }
|
||||
if(strlen($params['author']) > 40){ $errors['author'] .= 'Text is too long (> 40). '; }
|
||||
if(preg_match('/[\(\)\[\]\{\}\?\*\$\"\'\|<>=!;@#%§]/', $params['author'])){ $errors['author'] .= 'Only special chars like a,b a-b a_b a&b are allowed.'; }
|
||||
}
|
||||
|
||||
/* Validate Year */
|
||||
if(!isset($params['year'])){ $errors['year'] = 'Please add a year, e.g. 2017.'; }
|
||||
if(!preg_match('/^(\d{4})$/', $params['year'])){ $errors['year'] = 'Use four digits for the year like 2017.'; }
|
||||
|
||||
/* Validate Copyright */
|
||||
if(isset($params['copyright']) AND !in_array($params['copyright'], $copyright )){ $errors['copyright'] = 'Please select a valid copyright.'; }
|
||||
|
||||
/* Validate Theme */
|
||||
if(!isset($params['theme']) AND !in_array($params['theme'], $themes)){ $errors['theme'] = 'Please select a valid theme.'; }
|
||||
|
||||
/* Validate Startpage */
|
||||
if(isset($params['startpage'])){ $params['startpage'] = true; }else{ $params['startpage'] = false; }
|
||||
|
||||
/* Validate Folder Writable */
|
||||
if(!is_writable($this->c->get('settings')['settingsPath'])){ $errors['folder'] = 'Your settings folder is not writable.'; }
|
||||
|
||||
/* Prevent Title From Hacking */
|
||||
$params['title'] = htmlentities(stripslashes($params['title']));
|
||||
|
||||
if(!empty($errors))
|
||||
{
|
||||
$data = array(
|
||||
'themes' => $themes,
|
||||
'copyright' => $copyright,
|
||||
'errors' => $errors,
|
||||
'inputs' => $params,
|
||||
'base_url' => $base_url
|
||||
|
||||
);
|
||||
$this->c->view->render($response, '/setup.twig', $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $this->c->get('settings')['settingsPath'] . DIRECTORY_SEPARATOR . 'settings.yaml';
|
||||
$fh = fopen($file, 'w');
|
||||
$yaml = Yaml::dump($params);
|
||||
|
||||
file_put_contents($file, $yaml);
|
||||
|
||||
$data = array(
|
||||
'inputs' => $params,
|
||||
'base_url' => $base_url
|
||||
|
||||
);
|
||||
|
||||
$this->c->view->render($response, '/welcome.twig', $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getCopyright()
|
||||
{
|
||||
return array(
|
||||
"©",
|
||||
"CC-BY",
|
||||
"CC-BY-NC",
|
||||
"CC-BY-NC-ND",
|
||||
"CC-BY-NC-SA",
|
||||
"CC-BY-ND",
|
||||
"CC-BY-SA",
|
||||
"None"
|
||||
);
|
||||
}
|
||||
|
||||
private function getThemes()
|
||||
{
|
||||
$themeFolder = $this->c->get('settings')['rootPath'] . $this->c->get('settings')['themeFolder'];
|
||||
$themeFolderC = scandir($themeFolder);
|
||||
$themes = array();
|
||||
foreach ($themeFolderC as $key => $theme)
|
||||
{
|
||||
if (!in_array($theme, array(".","..")))
|
||||
{
|
||||
if (is_dir($themeFolder . DIRECTORY_SEPARATOR . $theme))
|
||||
{
|
||||
$themes[] = $theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $themes;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
81
system/Models/Cache.php
Normal file
81
system/Models/Cache.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class Cache
|
||||
{
|
||||
private $cachePath;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$cachePath = getcwd() . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
|
||||
if(!is_dir($cachePath)){
|
||||
mkdir($cachePath, 0774, true) or die('Please create a cache folder in your root and make it writable.');
|
||||
}
|
||||
is_writable($cachePath) or die('Your cache folder is not writable.');
|
||||
$this->cachePath = $cachePath;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
if(isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL'] == 'max-age=0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$requestFile = $this->cachePath.'request.txt';
|
||||
if(!file_exists($requestFile))
|
||||
{
|
||||
$this->writeFile($requestFile, time());
|
||||
return false;
|
||||
}
|
||||
|
||||
$lastRequest = file_get_contents($requestFile);
|
||||
if(time() - $lastRequest > 600)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function refresh($data, $name)
|
||||
{
|
||||
$sData = serialize($data);
|
||||
$dataFile = $this->cachePath.$name.'.txt';
|
||||
$requestFile = $this->cachePath.'request.txt';
|
||||
|
||||
$this->writeFile($dataFile, $sData);
|
||||
$this->writeFile($requestFile, time());
|
||||
}
|
||||
|
||||
public function getData($name)
|
||||
{
|
||||
if (file_exists($this->cachePath.$name.'.txt'))
|
||||
{
|
||||
$data = file_get_contents($this->cachePath.$name.'.txt');
|
||||
$data = unserialize($data);
|
||||
return $data;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function clearData($name)
|
||||
{
|
||||
/* todo */
|
||||
}
|
||||
|
||||
public function clearAll()
|
||||
{
|
||||
/* todo */
|
||||
}
|
||||
|
||||
public function writeFile($file, $data)
|
||||
{
|
||||
$fp = fopen($file, "w");
|
||||
fwrite($fp, $data);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
274
system/Models/Folder.php
Normal file
274
system/Models/Folder.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
use \URLify;
|
||||
|
||||
class Folder
|
||||
{
|
||||
/*
|
||||
* scans content of a folder recursively
|
||||
* vars: folder path as string
|
||||
* returns: multi-dimensional array with names of folders and files
|
||||
*/
|
||||
public static function scanFolder($folderPath)
|
||||
{
|
||||
$folderItems = scandir($folderPath);
|
||||
$folderContent = array();
|
||||
|
||||
foreach ($folderItems as $key => $item)
|
||||
{
|
||||
if (!in_array($item, array(".","..")))
|
||||
{
|
||||
if (is_dir($folderPath . DIRECTORY_SEPARATOR . $item))
|
||||
{
|
||||
$subFolder = $item;
|
||||
$folderContent[$subFolder] = self::scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $item;
|
||||
$folderContent[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $folderContent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transforms array of folder item into an array of item-objects with additional information for each item
|
||||
* vars: multidimensional array with folder- and file-names
|
||||
* returns: array of objects. Each object contains information about an item (file or folder).
|
||||
*/
|
||||
public static function getFolderContentDetails(array $folderContent, $baseUrl, $fullSlug = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
|
||||
{
|
||||
$contentDetails = [];
|
||||
$iteration = 0;
|
||||
$chapternr = 1;
|
||||
|
||||
foreach($folderContent as $key => $name)
|
||||
{
|
||||
$item = new \stdClass();
|
||||
|
||||
if(is_array($name))
|
||||
{
|
||||
$nameParts = self::getStringParts($key);
|
||||
|
||||
$item->originalName = $key;
|
||||
$item->elementType = 'folder';
|
||||
$item->index = array_search('index.md', $name) === false ? false : true;
|
||||
$item->order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
|
||||
$item->name = implode(" ",$nameParts);
|
||||
$item->name = iconv('ISO-8859-15', 'UTF-8', $item->name);
|
||||
$item->slug = implode("-",$nameParts);
|
||||
$item->slug = URLify::filter(iconv('ISO-8859-15', 'UTF-8', $item->slug));
|
||||
$item->path = $fullPath . DIRECTORY_SEPARATOR . $key;
|
||||
$item->urlRel = $fullSlug . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlug . '/' . $item->slug;
|
||||
$item->key = $iteration;
|
||||
$item->keyPath = $keyPath ? $keyPath . '.' . $iteration : $iteration;
|
||||
$item->keyPathArray = explode('.', $item->keyPath);
|
||||
$item->chapter = $chapter ? $chapter . '.' . $chapternr : $chapternr;
|
||||
|
||||
$item->folderContent = self::getFolderContentDetails($name, $baseUrl, $item->urlRel, $item->path, $item->keyPath, $item->chapter);
|
||||
}
|
||||
else
|
||||
{
|
||||
$nameParts = self::getStringParts($name);
|
||||
$fileType = array_pop($nameParts);
|
||||
|
||||
if($name == 'index.md' || $fileType !== 'md' ) break;
|
||||
|
||||
$item->originalName = $name;
|
||||
$item->elementType = 'file';
|
||||
$item->fileType = $fileType;
|
||||
$item->order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
|
||||
$item->name = implode(" ",$nameParts);
|
||||
$item->name = iconv('ISO-8859-15', 'UTF-8', $item->name);
|
||||
$item->slug = implode("-",$nameParts);
|
||||
$item->slug = URLify::filter(iconv('ISO-8859-15', 'UTF-8', $item->slug));
|
||||
$item->path = $fullPath . DIRECTORY_SEPARATOR . $name;
|
||||
$item->key = $iteration;
|
||||
$item->keyPath = $keyPath . '.' . $iteration;
|
||||
$item->keyPathArray = explode('.',$item->keyPath);
|
||||
$item->chapter = $chapter . '.' . $chapternr;
|
||||
$item->urlRel = $fullSlug . '/' . $item->slug;
|
||||
$item->urlAbs = $baseUrl . $fullSlug . '/' . $item->slug;
|
||||
}
|
||||
$iteration++;
|
||||
$chapternr++;
|
||||
$contentDetails[] = $item;
|
||||
}
|
||||
return $contentDetails;
|
||||
}
|
||||
|
||||
public static function getItemForUrl($folderContentDetails, $url, $result = NULL)
|
||||
{
|
||||
foreach($folderContentDetails as $key => $item)
|
||||
{
|
||||
if($item->urlRel === $url)
|
||||
{
|
||||
$item->active = true;
|
||||
$result = $item;
|
||||
}
|
||||
elseif($item->elementType === "folder")
|
||||
{
|
||||
$result = self::getItemForUrl($item->folderContent, $url, $result);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getPagingForItem($content, $item)
|
||||
{
|
||||
$keyPos = count($item->keyPathArray)-1;
|
||||
$thisChapArray = $item->keyPathArray;
|
||||
$nextItemArray = $item->keyPathArray;
|
||||
$prevItemArray = $item->keyPathArray;
|
||||
|
||||
$item->thisChapter = false;
|
||||
$item->prevItem = false;
|
||||
$item->nextItem = false;
|
||||
|
||||
|
||||
/************************
|
||||
* ADD THIS CHAPTER *
|
||||
************************/
|
||||
|
||||
if($keyPos > 0)
|
||||
{
|
||||
array_pop($thisChapArray);
|
||||
$item->thisChapter = self::getItemWithKeyPath($content, $thisChapArray);
|
||||
}
|
||||
|
||||
/************************
|
||||
* ADD NEXT ITEM *
|
||||
************************/
|
||||
|
||||
if($item->elementType == 'folder')
|
||||
{
|
||||
/* get the first element in the folder */
|
||||
$item->nextItem = isset($item->folderContent[0]) ? $item->folderContent[0] : false;
|
||||
}
|
||||
|
||||
if(!$item->nextItem)
|
||||
{
|
||||
$nextItemArray[$keyPos]++;
|
||||
$item->nextItem = self::getItemWithKeyPath($content, $nextItemArray);
|
||||
}
|
||||
|
||||
while(!$item->nextItem)
|
||||
{
|
||||
array_pop($nextItemArray);
|
||||
if(empty($nextItemArray)) break;
|
||||
$newKeyPos = count($nextItemArray)-1;
|
||||
$nextItemArray[$newKeyPos]++;
|
||||
$item->nextItem = self::getItemWithKeyPath($content, $nextItemArray);
|
||||
}
|
||||
|
||||
/************************
|
||||
* ADD PREVIOUS ITEM *
|
||||
************************/
|
||||
|
||||
if($prevItemArray[$keyPos] > 0)
|
||||
{
|
||||
$prevItemArray[$keyPos]--;
|
||||
$item->prevItem = self::getItemWithKeyPath($content, $prevItemArray);
|
||||
|
||||
if($item->prevItem && $item->prevItem->elementType == 'folder' && !empty($item->prevItem->folderContent))
|
||||
{
|
||||
/* get last item in folder */
|
||||
$item->prevItem = self::getLastItemOfFolder($item->prevItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$item->prevItem = $item->thisChapter;
|
||||
}
|
||||
|
||||
if($item->prevItem && $item->prevItem->elementType == 'folder'){ unset($item->prevItem->folderContent); }
|
||||
if($item->nextItem && $item->nextItem->elementType == 'folder'){ unset($item->nextItem->folderContent); }
|
||||
if($item->thisChapter){unset($item->thisChapter->folderContent); }
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public static function getItemWithKeyPath($content, array $searchArray)
|
||||
{
|
||||
$item = false;
|
||||
|
||||
foreach($searchArray as $key => $itemKey)
|
||||
{
|
||||
$item = isset($content[$itemKey]) ? clone($content[$itemKey]) : false;
|
||||
|
||||
unset($searchArray[$key]);
|
||||
if(!empty($searchArray) && $item)
|
||||
{
|
||||
return self::getItemWithKeyPath($item->folderContent, $searchArray);
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/* get breadcrumb as copied array, set elements active in original and mark parent element in original */
|
||||
public static function getBreadcrumb($content, $searchArray, $i = NULL, $breadcrumb = NULL)
|
||||
{
|
||||
if(!$i){ $i = 0; $breadcrumb = array();}
|
||||
|
||||
while($i < count($searchArray))
|
||||
{
|
||||
$item = $content[$searchArray[$i]];
|
||||
$item->active = true;
|
||||
if($i == count($searchArray)-2)
|
||||
{
|
||||
$item->activeParent = true;
|
||||
}
|
||||
|
||||
$copy = clone($item);
|
||||
if($copy->elementType == 'folder')
|
||||
{
|
||||
unset($copy->folderContent);
|
||||
$content = $item->folderContent;
|
||||
}
|
||||
$breadcrumb[] = $copy;
|
||||
|
||||
$i++;
|
||||
return self::getBreadcrumb($content, $searchArray, $i++, $breadcrumb);
|
||||
}
|
||||
return $breadcrumb;
|
||||
}
|
||||
|
||||
public static function getParentItem($content, $searchArray, $iteration = NULL)
|
||||
{
|
||||
if(!$iteration){ $iteration = 0; }
|
||||
while($iteration < count($searchArray)-2)
|
||||
{
|
||||
$content = $content[$searchArray[$iteration]]->folderContent;
|
||||
$iteration++;
|
||||
return self::getParentItem($content, $searchArray, $iteration);
|
||||
}
|
||||
return $content[$searchArray[$iteration]];
|
||||
}
|
||||
|
||||
private static function getLastItemOfFolder($folder)
|
||||
{
|
||||
$lastItem = end($folder->folderContent);
|
||||
if(is_object($lastItem) && $lastItem->elementType == 'folder' && !empty($lastItem->folderContent))
|
||||
{
|
||||
return self::getLastItemOfFolder($lastItem);
|
||||
}
|
||||
return $lastItem;
|
||||
}
|
||||
|
||||
public static function getStringParts($name)
|
||||
{
|
||||
return preg_split('/[\-\.\_\=\+\?\!\*\#\(\)\/ ]/',$name);
|
||||
}
|
||||
|
||||
public static function getFileType($fileName)
|
||||
{
|
||||
$parts = preg_split('/\./',$fileName);
|
||||
return end($parts);
|
||||
}
|
||||
}
|
||||
?>
|
28
system/Models/Helpers.php
Normal file
28
system/Models/Helpers.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace System\Models;
|
||||
|
||||
class Helpers{
|
||||
|
||||
public static function printTimer($timer)
|
||||
{
|
||||
$lastTime = NULL;
|
||||
$table = '<html><body><table>';
|
||||
$table .= '<tr><th>Breakpoint</th><th>Time</th><th>Duration</th></tr>';
|
||||
foreach($timer as $breakpoint => $time)
|
||||
{
|
||||
$duration = $time - $lastTime;
|
||||
|
||||
$table .= '<tr>';
|
||||
$table .= '<td>' . $breakpoint . '</td>';
|
||||
$table .= '<td>' . $time . '</td>';
|
||||
$table .= '<td>' . $duration . '</td>';
|
||||
$table .= '</tr>';
|
||||
|
||||
$lastTime = $time;
|
||||
}
|
||||
$table .= '</table></body></html>';
|
||||
echo $table;
|
||||
exit;
|
||||
}
|
||||
}
|
7
system/Routes/api.php
Normal file
7
system/Routes/api.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
/*
|
||||
use App\Controllers\ApiController;
|
||||
|
||||
$app->get('/api', ApiController::class . ':index' )->setName('api.index');
|
||||
*/
|
||||
?>
|
13
system/Routes/web.php
Normal file
13
system/Routes/web.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use System\Controllers\PageController;
|
||||
use System\Controllers\SetupController;
|
||||
|
||||
if(!isset($userSettings))
|
||||
{
|
||||
$app->get('/setup', SetupController::class . ':setup')->setName('setup');
|
||||
$app->post('/setup', SetupController::class . ':save')->setName('save');
|
||||
}
|
||||
|
||||
$app->get('/[{params:.*}]', PageController::class . ':index');
|
||||
?>
|
461
system/author/css/normalize.css
vendored
Normal file
461
system/author/css/normalize.css
vendored
Normal file
@@ -0,0 +1,461 @@
|
||||
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/**
|
||||
* 1. Change the default font family in all browsers (opinionated).
|
||||
* 2. Correct the line height in all browsers.
|
||||
* 3. Prevent adjustments of font size after orientation changes in
|
||||
* IE on Windows Phone and in iOS.
|
||||
*/
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
line-height: 1.15; /* 2 */
|
||||
-ms-text-size-adjust: 100%; /* 3 */
|
||||
-webkit-text-size-adjust: 100%; /* 3 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
footer,
|
||||
header,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
figcaption,
|
||||
figure,
|
||||
main { /* 1 */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Remove the gray background on active links in IE 10.
|
||||
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent; /* 1 */
|
||||
-webkit-text-decoration-skip: objects; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the outline on focused links when they are also active or hovered
|
||||
* in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline-width: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Firefox 39-.
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font style in Android 4.3-.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct background and color in IE 9-.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10-.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the overflow in IE.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers (opinionated).
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
* controls in Android 4.
|
||||
* 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
html [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the border, margin, and padding in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct display in IE 9-.
|
||||
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10-.
|
||||
* 2. Remove the padding in IE 10-.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
*/
|
||||
|
||||
details, /* 1 */
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Scripting
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hidden
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
231
system/author/css/style.css
Normal file
231
system/author/css/style.css
Normal file
@@ -0,0 +1,231 @@
|
||||
/**********************
|
||||
* HELPERS *
|
||||
**********************/
|
||||
|
||||
a, a:link, a:visited, a:focus, a:hover, a:active, button, .button, input{
|
||||
-webkit-transition: all 0.2s ease;
|
||||
-moz-transition: all 0.2s ease;
|
||||
-o-transition: all 0.2s ease;
|
||||
-ms-transition: all 0.2s ease;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* COLORS *
|
||||
**********************/
|
||||
|
||||
body{ background: #f9f8f6; color: #444; }
|
||||
.card{ background: #FFF; }
|
||||
.card header{ background: #e0494c; color: #f9f8f6; }
|
||||
.onoffswitch-label { border: 0px solid #DDD; }
|
||||
.onoffswitch-inner:before { background: #8ce196; color: #f9f8f6; }
|
||||
.onoffswitch-inner:after { background: #e0474c; color: #f9f8f6; }
|
||||
.onoffswitch-switch { background: #f9f8f6; border: 1px solid #999; }
|
||||
input, select{ border: 1px solid #ddd; background: #fff; }
|
||||
select:focus, input:focus{ border: 1px solid #FFF; outline: none; box-shadow: 0 0 2px #e0474c; }
|
||||
input[type="submit"]{ border: 2px solid #FFF; background: #e0474c; color: #f9f8f6; }
|
||||
input[type="submit"]:hover{ background: #FFF; color: #444; }
|
||||
a.button{ border: 2px solid #e0474c; background: #e0474c; color: #f9f8f6; }
|
||||
a.button:hover{ border: 2px solid #e0474c; background: #FFF; color: #444; }
|
||||
.error label{ color: #e0474c; }
|
||||
.error input, .error select{ border: 1px solid #e0474c; }
|
||||
.error small, .error p{ color: #e0474c; }
|
||||
|
||||
/********************
|
||||
* FONTS *
|
||||
********************/
|
||||
|
||||
header, nav, h1, h2, h3, h4, h5, h6{
|
||||
font-family: arial, sans-serif;
|
||||
}
|
||||
|
||||
/********************
|
||||
* HEADLINES *
|
||||
********************/
|
||||
|
||||
h1, h2, h3, h4, h5, h6{ font-weight: 700; }
|
||||
h1{ font-size: 1em; margin: 0.6em 0 0.6em; }
|
||||
h2{ font-size: 1em; margin: 0.6em 0 0.6em; }
|
||||
h3{ font-size: 1em; margin: 0.6em 0 0.6em; }
|
||||
|
||||
html,body{
|
||||
padding: 0;
|
||||
margin:0;
|
||||
}
|
||||
body{
|
||||
padding: 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.card{
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 400px;
|
||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12);
|
||||
}
|
||||
.card img{
|
||||
width: 100%;
|
||||
}
|
||||
.card header{
|
||||
display: inlin-block;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.card header h1{
|
||||
display: inline-block;
|
||||
}
|
||||
form{}
|
||||
fieldset{
|
||||
padding: 30px 20px;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
}
|
||||
label,.label{
|
||||
display: block;
|
||||
font-size: 0.65em;
|
||||
font-weight: 300;
|
||||
padding: 15px 0 0;
|
||||
line-height: 1.5em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.field{
|
||||
margin: 5px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.size100{
|
||||
width: 100%;
|
||||
}
|
||||
.size25, .size50, .size75{
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
.size75{ width: 74%; }
|
||||
.size50{ width: 49%; }
|
||||
.size25{ width: 24%; }
|
||||
input, select{
|
||||
display: inline-block;
|
||||
margin-top: 5px;
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
font-size: 0.8em;
|
||||
box-sizing: border-box;
|
||||
min-height: 42px;
|
||||
}
|
||||
input{
|
||||
padding: 10px;
|
||||
}
|
||||
select{
|
||||
padding: 8px;
|
||||
}
|
||||
input[type="submit"]{
|
||||
border-radius: 3px;
|
||||
float: right;
|
||||
margin-top: 0px;
|
||||
width: 150px;
|
||||
}
|
||||
input[type="submit"]:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Select Button, see https://codepen.io/vkjgr/pen/VYMeXp */
|
||||
select {
|
||||
/* reset */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
|
||||
/* style */
|
||||
background-image:
|
||||
linear-gradient(45deg, transparent 50%, #444 50%),
|
||||
linear-gradient(135deg, #444 50%, transparent 50%),
|
||||
linear-gradient(to right, #f9f8f6, #f9f8f6);
|
||||
background-position:
|
||||
calc(100% - 20px) calc(1em + 2px),
|
||||
calc(100% - 15px) calc(1em + 2px),
|
||||
100% 0;
|
||||
background-size:
|
||||
5px 5px,
|
||||
5px 5px,
|
||||
2.8em 2.8em;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* On Off Switch */
|
||||
.onoffswitch {
|
||||
margin-top: 5px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
-webkit-user-select:none;
|
||||
-moz-user-select:none;
|
||||
-ms-user-select:none;
|
||||
}
|
||||
.onoffswitch label{
|
||||
padding: 0;
|
||||
}
|
||||
.onoffswitch-checkbox {
|
||||
display: none;
|
||||
}
|
||||
.onoffswitch-label {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
.onoffswitch-inner {
|
||||
display: block;
|
||||
width: 200%;
|
||||
margin-left: -100%;
|
||||
transition: margin 0.3s ease-in 0s;
|
||||
}
|
||||
.onoffswitch-inner:before, .onoffswitch-inner:after {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 50%;
|
||||
padding: 10px 0;
|
||||
font-size: 1.5em;
|
||||
line-height: 1.9em;
|
||||
font-family: Trebuchet, Arial, sans-serif;
|
||||
font-weight: bold;
|
||||
box-sizing: border-box;
|
||||
min-height: 42px;
|
||||
}
|
||||
.onoffswitch-inner:before {
|
||||
content: "ON";
|
||||
padding-left: 20px;
|
||||
}
|
||||
.onoffswitch-inner:after {
|
||||
content: "OFF";
|
||||
padding-right: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
.onoffswitch-switch {
|
||||
display: block;
|
||||
width: 18px;
|
||||
margin: 6px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 60%;
|
||||
border-radius: 20px;
|
||||
transition: all 0.3s ease-in 0s;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
|
||||
margin-left: 0;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
|
||||
right: 0px;
|
||||
}
|
||||
.welcome{
|
||||
padding: 20px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
a.button{
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
}
|
18
system/author/layout.twig
Normal file
18
system/author/layout.twig
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<meta name="description" content="Setup your TYPEMILL website">
|
||||
|
||||
<link rel="stylesheet" href="{{ base_url }}/system/author/css/normalize.css" />
|
||||
<link rel="stylesheet" href="{{ base_url }}/system/author/css/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="main">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
74
system/author/setup.twig
Normal file
74
system/author/setup.twig
Normal file
@@ -0,0 +1,74 @@
|
||||
{% extends '/layout.twig' %}
|
||||
|
||||
{% block title %}Setup{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<form method="POST" action="{{ base_url() }}/setup">
|
||||
<header>
|
||||
<h1>Setup</h1>
|
||||
<input type="submit" value="save" />
|
||||
</header>
|
||||
<fieldset>
|
||||
{% if errors.folder %}
|
||||
<div class="field error">
|
||||
<p>{{ errors.folder }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="field size100{% if errors.title %} error{% endif %}">
|
||||
<label for="title">Website Title *</label>
|
||||
<input type="text" name="title" id="title" pattern=".{2,20}" required title="Use 2 to 20 characters." value="{{ inputs.title }}" />
|
||||
{% if errors.title %}<small>{{ errors.title }}</small>{% endif %}
|
||||
</div>
|
||||
<div class="field size100{% if errors.author %} error{% endif %}">
|
||||
<label for="author">Author</label>
|
||||
<input type="text" name="author" id="author" value="{{ inputs.author }}" pattern="[^()/><\]\{\}\?\$@#!*%§=[\\\x22;:|]{2,40}" title="Use 2 to 40 characters. Only the following special characters are allowed: a,b a.b a-b a_b a&b a+b" />
|
||||
{% if errors.author %}<small>{{ errors.author }}</small>{% endif %}
|
||||
</div>
|
||||
<div class="field size75{% if errors.copyright %} error{% endif %}">
|
||||
<label for="copyright">Copyright/Licence</label>
|
||||
<select name="copyright" id="copyright">
|
||||
{% for copy in copyright %}
|
||||
<option value="{{ copy }}">{{ copy }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if errors.copyright %}<small>{{ errors.copyright }}</small>{% endif %}
|
||||
</div>
|
||||
<div class="field size25{% if errors.year %} error{% endif %}">
|
||||
<label for="year">Year *</label>
|
||||
<input type="text" name="year" id="year" value="{{ "now"|date("Y") }}" pattern="[0-9]{4}" required title="Use a valid year, e.g. 2017" />
|
||||
{% if errors.year %}<small>{{ errors.year }}</small>{% endif %}
|
||||
</div>
|
||||
<div class="field size75{% if errors.theme %} error{% endif %}">
|
||||
<label for="theme">Theme</label>
|
||||
<select name="theme" id="themeSwitch">
|
||||
{% for theme in themes %}
|
||||
<option value="{{ theme }}">{{ theme }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if errors.theme %}<small>{{ errors.theme }}</small>{% endif %}
|
||||
</div>
|
||||
<div class="field size25"><span class="label">Startpage</label>
|
||||
<div class="onoffswitch">
|
||||
<input type="checkbox" name="startpage" class="onoffswitch-checkbox" id="startpage" checked >
|
||||
<label class="onoffswitch-label" for="startpage">
|
||||
<span class="onoffswitch-inner"></span>
|
||||
<span class="onoffswitch-switch"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<img id="themePrev" src="{{ base_url() }}/themes/typemill/typemill.jpg">
|
||||
</div>
|
||||
<script>
|
||||
var themeSwitch = document.getElementById("themeSwitch"),
|
||||
themePrev = document.getElementById("themePrev"),
|
||||
themePath = themePrev.src.split("themes")[0];
|
||||
themeSwitch.addEventListener('change', function()
|
||||
{
|
||||
themePrev.src = themePath + 'themes/' + themeSwitch.value + '/' + themeSwitch.value + '.jpg';
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
17
system/author/welcome.twig
Normal file
17
system/author/welcome.twig
Normal file
@@ -0,0 +1,17 @@
|
||||
{% extends '/layout.twig' %}
|
||||
|
||||
{% block title %}Setup Welcome{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<header>
|
||||
<h1>Congratulations!</h1>
|
||||
</header>
|
||||
<div class="welcome">
|
||||
<p>Hello {{ author }}!</p>
|
||||
<p>Your settings are stored in your settings folder now. If you want to change the settings, simply open the file "settings.yaml" and edit them.</p>
|
||||
<p>Not sure how to start? Simply create some content for your new website or visit the homepage and read the documentation... </p>
|
||||
<a class="button" href="{{ base_url }}">Homepage</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
7
system/autoload.php
Normal file
7
system/autoload.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit7102ebcc2359dc2658965039bfa4c68f::getLoader();
|
23
system/settings.php
Normal file
23
system/settings.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
DEFINE('DS', DIRECTORY_SEPARATOR);
|
||||
|
||||
return [
|
||||
'settings' => [
|
||||
'title' => 'TYPEMILL',
|
||||
'author' => 'unknown',
|
||||
'copyright' => 'copyright',
|
||||
'startpage' => true,
|
||||
'rootPath' => __DIR__ . DS . '..' . DS,
|
||||
'theme' => ($theme = 'typemill'),
|
||||
'themeFolder' => ($themeFolder = 'themes'),
|
||||
'themePath' => __DIR__ . DS . '..' . DS . $themeFolder . DS . $theme,
|
||||
'settingsPath' => __DIR__ . DS . '..' . DS . 'settings',
|
||||
'authorPath' => __DIR__ . DS . 'author' . DS,
|
||||
'contentFolder' => 'content',
|
||||
'displayErrorDetails' => false,
|
||||
'version' => '1.0.0'
|
||||
],
|
||||
];
|
||||
|
||||
?>
|
77
system/system.php
Normal file
77
system/system.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/************************
|
||||
* START SESSION *
|
||||
************************/
|
||||
|
||||
session_start();
|
||||
|
||||
/************************
|
||||
* LOAD SETTINGS *
|
||||
************************/
|
||||
|
||||
$settings = require_once( __DIR__ . '/settings.php');
|
||||
|
||||
if(file_exists($settings['settings']['settingsPath'] . DIRECTORY_SEPARATOR . 'settings.yaml'))
|
||||
{
|
||||
$yaml = new \Symfony\Component\Yaml\Parser();
|
||||
|
||||
try {
|
||||
$userSettings = $yaml->parse( file_get_contents($settings['settings']['settingsPath'] . DIRECTORY_SEPARATOR . 'settings.yaml' ) );
|
||||
} catch (ParseException $e) {
|
||||
printf("Unable to parse the YAML string: %s", $e->getMessage());
|
||||
}
|
||||
|
||||
$settings = array('settings' => array_merge($settings['settings'], $userSettings));
|
||||
}
|
||||
|
||||
/************************
|
||||
* INITIATE SLIM *
|
||||
************************/
|
||||
|
||||
$app = new \Slim\App($settings);
|
||||
|
||||
/************************
|
||||
* SLIM CONTAINER *
|
||||
************************/
|
||||
|
||||
$container = $app->getContainer();
|
||||
|
||||
/************************
|
||||
* LOAD TWIG *
|
||||
************************/
|
||||
$container['view'] = function ($container) use ($settings){
|
||||
$path = array($settings['settings']['themePath'], $settings['settings']['authorPath']);
|
||||
$view = new \Slim\Views\Twig( $path, [
|
||||
'cache' => false,
|
||||
'autoescape' => false
|
||||
]);
|
||||
|
||||
// Instantiate and add Slim specific extension
|
||||
$basePath = rtrim(str_ireplace('index.php', '', $container['request']->getUri()->getBasePath()), '/');
|
||||
$view->addExtension(new Slim\Views\TwigExtension($container['router'], $basePath));
|
||||
|
||||
return $view;
|
||||
};
|
||||
|
||||
/************************
|
||||
* LOAD FLASH MESSAGES *
|
||||
************************/
|
||||
|
||||
$container['flash'] = function () {
|
||||
return new \Slim\Flash\Messages();
|
||||
};
|
||||
|
||||
/************************
|
||||
* NOT FOUND HANDLER *
|
||||
************************/
|
||||
|
||||
$container['notFoundHandler'] = function($c)
|
||||
{
|
||||
return new \System\Handlers\NotFoundHandler($c['view']);
|
||||
};
|
||||
|
||||
require __DIR__ . '/Routes/web.php';
|
||||
require __DIR__ . '/Routes/api.php';
|
||||
|
||||
?>
|
7
system/vendor/autoload.php
vendored
Normal file
7
system/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit836351be733ecbf4741aea17e1973480::getLoader();
|
445
system/vendor/composer/ClassLoader.php
vendored
Normal file
445
system/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see http://www.php-fig.org/psr/psr-0/
|
||||
* @see http://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
private $prefixesPsr0 = array();
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
private $classMapAuthoritative = false;
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath.'\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
$length = $this->prefixLengthsPsr4[$first][$search];
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
21
system/vendor/composer/LICENSE
vendored
Normal file
21
system/vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
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.
|
||||
|
9
system/vendor/composer/autoload_classmap.php
vendored
Normal file
9
system/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
);
|
10
system/vendor/composer/autoload_files.php
vendored
Normal file
10
system/vendor/composer/autoload_files.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
|
||||
);
|
14
system/vendor/composer/autoload_namespaces.php
vendored
Normal file
14
system/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'URLify' => array($vendorDir . '/jbroadway/urlify'),
|
||||
'Twig_' => array($vendorDir . '/twig/twig/lib'),
|
||||
'Pimple' => array($vendorDir . '/pimple/pimple/src'),
|
||||
'ParsedownExtra' => array($vendorDir . '/erusev/parsedown-extra'),
|
||||
'Parsedown' => array($vendorDir . '/erusev/parsedown'),
|
||||
);
|
18
system/vendor/composer/autoload_psr4.php
vendored
Normal file
18
system/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname(dirname($vendorDir));
|
||||
|
||||
return array(
|
||||
'System\\' => array($baseDir . '/system'),
|
||||
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
|
||||
'Slim\\Views\\' => array($vendorDir . '/slim/twig-view/src'),
|
||||
'Slim\\Flash\\' => array($vendorDir . '/slim/flash/src'),
|
||||
'Slim\\' => array($vendorDir . '/slim/slim/Slim'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
|
||||
'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'),
|
||||
);
|
70
system/vendor/composer/autoload_real.php
vendored
Normal file
70
system/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit836351be733ecbf4741aea17e1973480
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit836351be733ecbf4741aea17e1973480', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit836351be733ecbf4741aea17e1973480', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require_once __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit836351be733ecbf4741aea17e1973480::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit836351be733ecbf4741aea17e1973480::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire836351be733ecbf4741aea17e1973480($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire836351be733ecbf4741aea17e1973480($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
117
system/vendor/composer/autoload_static.php
vendored
Normal file
117
system/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit836351be733ecbf4741aea17e1973480
|
||||
{
|
||||
public static $files = array (
|
||||
'253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'System\\' => 7,
|
||||
'Symfony\\Component\\Yaml\\' => 23,
|
||||
'Slim\\Views\\' => 11,
|
||||
'Slim\\Flash\\' => 11,
|
||||
'Slim\\' => 5,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
'Psr\\Container\\' => 14,
|
||||
),
|
||||
'I' =>
|
||||
array (
|
||||
'Interop\\Container\\' => 18,
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'FastRoute\\' => 10,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'System\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../../..' . '/system',
|
||||
),
|
||||
'Symfony\\Component\\Yaml\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/yaml',
|
||||
),
|
||||
'Slim\\Views\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/slim/twig-view/src',
|
||||
),
|
||||
'Slim\\Flash\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/slim/flash/src',
|
||||
),
|
||||
'Slim\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/slim/slim/Slim',
|
||||
),
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
),
|
||||
'Interop\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container',
|
||||
),
|
||||
'FastRoute\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/nikic/fast-route/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'U' =>
|
||||
array (
|
||||
'URLify' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/jbroadway/urlify',
|
||||
),
|
||||
),
|
||||
'T' =>
|
||||
array (
|
||||
'Twig_' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/twig/twig/lib',
|
||||
),
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Pimple' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/pimple/pimple/src',
|
||||
),
|
||||
'ParsedownExtra' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/erusev/parsedown-extra',
|
||||
),
|
||||
'Parsedown' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/erusev/parsedown',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixesPsr0;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
667
system/vendor/composer/installed.json
vendored
Normal file
667
system/vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,667 @@
|
||||
[
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v1.2.0",
|
||||
"version_normalized": "1.2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/FastRoute.git",
|
||||
"reference": "b5f95749071c82a8e0f58586987627054400cdf6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6",
|
||||
"reference": "b5f95749071c82a8e0f58586987627054400cdf6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"time": "2017-01-19T11:35:12+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": [
|
||||
"router",
|
||||
"routing"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"version_normalized": "1.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2016-08-06T14:39:51+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pimple/pimple",
|
||||
"version": "v3.0.2",
|
||||
"version_normalized": "3.0.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/silexphp/Pimple.git",
|
||||
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
|
||||
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2015-09-11T15:10:35+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Pimple": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Pimple, a simple Dependency Injection Container",
|
||||
"homepage": "http://pimple.sensiolabs.org",
|
||||
"keywords": [
|
||||
"container",
|
||||
"dependency injection"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "slim/twig-view",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Twig-View.git",
|
||||
"reference": "a743ac45e2a089942159dda499c5ef5bc5f6bfa6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Twig-View/zipball/a743ac45e2a089942159dda499c5ef5bc5f6bfa6",
|
||||
"reference": "a743ac45e2a089942159dda499c5ef5bc5f6bfa6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"twig/twig": "^1.18|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8|^5.7"
|
||||
},
|
||||
"time": "2017-01-25T20:38:39+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Slim\\Views\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "hello@joshlockhart.com",
|
||||
"homepage": "http://joshlockhart.com"
|
||||
}
|
||||
],
|
||||
"description": "Slim Framework 3 view helper built on top of the Twig 2 templating component",
|
||||
"homepage": "http://slimframework.com",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"slim",
|
||||
"template",
|
||||
"twig",
|
||||
"view"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.0.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
||||
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2017-02-14T16:28:37+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"version": "1.2.0",
|
||||
"version_normalized": "1.2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/container-interop.git",
|
||||
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
|
||||
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"time": "2017-02-14T19:40:03+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/Interop/Container/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"homepage": "https://github.com/container-interop/container-interop"
|
||||
},
|
||||
{
|
||||
"name": "jbroadway/urlify",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jbroadway/urlify.git",
|
||||
"reference": "99bb78cd9002d0e9ce479bb81635eb665e37e981"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jbroadway/urlify/zipball/99bb78cd9002d0e9ce479bb81635eb665e37e981",
|
||||
"reference": "99bb78cd9002d0e9ce479bb81635eb665e37e981",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2017-01-03T20:12:54+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"URLify": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Johnny Broadway",
|
||||
"email": "johnny@johnnybroadway.com",
|
||||
"homepage": "http://www.johnnybroadway.com/"
|
||||
}
|
||||
],
|
||||
"description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
|
||||
"homepage": "https://github.com/jbroadway/urlify",
|
||||
"keywords": [
|
||||
"encode",
|
||||
"iconv",
|
||||
"link",
|
||||
"slug",
|
||||
"translit",
|
||||
"transliterate",
|
||||
"transliteration",
|
||||
"url",
|
||||
"urlify"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "3.8.1",
|
||||
"version_normalized": "3.8.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "5385302707530b2bccee1769613ad769859b826d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/5385302707530b2bccee1769613ad769859b826d",
|
||||
"reference": "5385302707530b2bccee1769613ad769859b826d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/container-interop": "^1.2",
|
||||
"nikic/fast-route": "^1.0",
|
||||
"php": ">=5.5.0",
|
||||
"pimple/pimple": "^3.0",
|
||||
"psr/container": "^1.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^2.5"
|
||||
},
|
||||
"time": "2017-03-19T17:55:20+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Slim\\": "Slim"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Allen",
|
||||
"email": "rob@akrabat.com",
|
||||
"homepage": "http://akrabat.com"
|
||||
},
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "hello@joshlockhart.com",
|
||||
"homepage": "https://joshlockhart.com"
|
||||
},
|
||||
{
|
||||
"name": "Gabriel Manricks",
|
||||
"email": "gmanricks@me.com",
|
||||
"homepage": "http://gabrielmanricks.com"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Smith",
|
||||
"email": "a.smith@silentworks.co.uk",
|
||||
"homepage": "http://silentworks.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
|
||||
"homepage": "https://slimframework.com",
|
||||
"keywords": [
|
||||
"api",
|
||||
"framework",
|
||||
"micro",
|
||||
"router"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown-extra",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/erusev/parsedown-extra.git",
|
||||
"reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/0db5cce7354e4b76f155d092ab5eb3981c21258c",
|
||||
"reference": "0db5cce7354e4b76f155d092ab5eb3981c21258c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"erusev/parsedown": "~1.4"
|
||||
},
|
||||
"time": "2015-11-01T10:19:22+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"ParsedownExtra": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Emanuil Rusev",
|
||||
"email": "hello@erusev.com",
|
||||
"homepage": "http://erusev.com"
|
||||
}
|
||||
],
|
||||
"description": "An extension of Parsedown that adds support for Markdown Extra.",
|
||||
"homepage": "https://github.com/erusev/parsedown-extra",
|
||||
"keywords": [
|
||||
"markdown",
|
||||
"markdown extra",
|
||||
"parsedown",
|
||||
"parser"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
"version": "1.6.2",
|
||||
"version_normalized": "1.6.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/erusev/parsedown.git",
|
||||
"reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01",
|
||||
"reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2017-03-29T16:04:15+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Parsedown": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Emanuil Rusev",
|
||||
"email": "hello@erusev.com",
|
||||
"homepage": "http://erusev.com"
|
||||
}
|
||||
],
|
||||
"description": "Parser for Markdown.",
|
||||
"homepage": "http://parsedown.org",
|
||||
"keywords": [
|
||||
"markdown",
|
||||
"parser"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "slim/flash",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim-Flash.git",
|
||||
"reference": "3c9a26b3163820acc48080336c504d0a3cac6f30"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim-Flash/zipball/3c9a26b3163820acc48080336c504d0a3cac6f30",
|
||||
"reference": "3c9a26b3163820acc48080336c504d0a3cac6f30",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0"
|
||||
},
|
||||
"time": "2016-11-11T16:29:19+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Slim\\Flash\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "hello@joshlockhart.com",
|
||||
"homepage": "http://joshlockhart.com"
|
||||
}
|
||||
],
|
||||
"description": "Slim Framework Flash message service provider",
|
||||
"homepage": "http://slimframework.com",
|
||||
"keywords": [
|
||||
"flash",
|
||||
"framework",
|
||||
"message",
|
||||
"provider",
|
||||
"slim"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v1.33.0",
|
||||
"version_normalized": "1.33.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a",
|
||||
"reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/container": "^1.0",
|
||||
"symfony/debug": "~2.7",
|
||||
"symfony/phpunit-bridge": "~3.3@dev"
|
||||
},
|
||||
"time": "2017-03-22T15:40:09+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.33-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Twig_": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com",
|
||||
"homepage": "http://fabien.potencier.org",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Armin Ronacher",
|
||||
"email": "armin.ronacher@active-4.com",
|
||||
"role": "Project Founder"
|
||||
},
|
||||
{
|
||||
"name": "Twig Team",
|
||||
"homepage": "http://twig.sensiolabs.org/contributors",
|
||||
"role": "Contributors"
|
||||
}
|
||||
],
|
||||
"description": "Twig, the flexible, fast, and secure template language for PHP",
|
||||
"homepage": "http://twig.sensiolabs.org",
|
||||
"keywords": [
|
||||
"templating"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v2.8.19",
|
||||
"version_normalized": "2.8.19.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "286d84891690b0e2515874717e49360d1c98a703"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/286d84891690b0e2515874717e49360d1c98a703",
|
||||
"reference": "286d84891690b0e2515874717e49360d1c98a703",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"time": "2017-03-20T09:41:44+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.8-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com"
|
||||
}
|
||||
]
|
3
system/vendor/container-interop/container-interop/.gitignore
vendored
Normal file
3
system/vendor/container-interop/container-interop/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
composer.lock
|
||||
composer.phar
|
||||
/vendor/
|
20
system/vendor/container-interop/container-interop/LICENSE
vendored
Normal file
20
system/vendor/container-interop/container-interop/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 container-interop
|
||||
|
||||
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.
|
148
system/vendor/container-interop/container-interop/README.md
vendored
Normal file
148
system/vendor/container-interop/container-interop/README.md
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
# Container Interoperability
|
||||
|
||||
[](https://packagist.org/packages/container-interop/container-interop)
|
||||
[](https://packagist.org/packages/container-interop/container-interop)
|
||||
|
||||
## Deprecation warning!
|
||||
|
||||
Starting Feb. 13th 2017, container-interop is officially deprecated in favor of [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md).
|
||||
Container-interop has been the test-bed of PSR-11. From v1.2, container-interop directly extends PSR-11 interfaces.
|
||||
Therefore, all containers implementing container-interop are now *de-facto* compatible with PSR-11.
|
||||
|
||||
- Projects implementing container-interop interfaces are encouraged to directly implement PSR-11 interfaces instead.
|
||||
- Projects consuming container-interop interfaces are very strongly encouraged to directly type-hint on PSR-11 interfaces, in order to be compatible with PSR-11 containers that are not compatible with container-interop.
|
||||
|
||||
Regarding the delegate lookup feature, that is present in container-interop and not in PSR-11, the feature is actually a design pattern. It is therefore not deprecated. Documentation regarding this design pattern will be migrated from this repository into a separate website in the future.
|
||||
|
||||
## About
|
||||
|
||||
*container-interop* tries to identify and standardize features in *container* objects (service locators,
|
||||
dependency injection containers, etc.) to achieve interoperability.
|
||||
|
||||
Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations.
|
||||
|
||||
If PHP projects that provide container implementations begin to adopt these common standards, then PHP
|
||||
applications and projects that use containers can depend on the common interfaces instead of specific
|
||||
implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume
|
||||
*any* container implementation that can be adapted to these interfaces.
|
||||
|
||||
The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being
|
||||
worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope
|
||||
this project will pave the way for one or more future PSRs.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
You can install this package through Composer:
|
||||
|
||||
```json
|
||||
composer require container-interop/container-interop
|
||||
```
|
||||
|
||||
The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility
|
||||
between minor versions.
|
||||
|
||||
## Standards
|
||||
|
||||
### Available
|
||||
|
||||
- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php).
|
||||
[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md).
|
||||
Describes the interface of a container that exposes methods to read its entries.
|
||||
- [*Delegate lookup feature*](docs/Delegate-lookup.md).
|
||||
[Meta Document](docs/Delegate-lookup-meta.md).
|
||||
Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This
|
||||
feature lets several containers work together in a single application.
|
||||
|
||||
### Proposed
|
||||
|
||||
View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC)
|
||||
|
||||
## Compatible projects
|
||||
|
||||
### Projects implementing `ContainerInterface`
|
||||
|
||||
- [Acclimate](https://github.com/jeremeamia/acclimate-container): Adapters for
|
||||
Aura.Di, Laravel, Nette DI, Pimple, Symfony DI, ZF2 Service manager, ZF2
|
||||
Dependency injection and any container using `ArrayAccess`
|
||||
- [Aura.Di](https://github.com/auraphp/Aura.Di)
|
||||
- [auryn-container-interop](https://github.com/elazar/auryn-container-interop)
|
||||
- [Burlap](https://github.com/codeeverything/burlap)
|
||||
- [Chernozem](https://github.com/pyrsmk/Chernozem)
|
||||
- [Data Manager](https://github.com/chrismichaels84/data-manager)
|
||||
- [Disco](https://github.com/bitexpert/disco)
|
||||
- [InDI](https://github.com/idealogica/indi)
|
||||
- [League/Container](http://container.thephpleague.com/)
|
||||
- [Mouf](http://mouf-php.com)
|
||||
- [Njasm Container](https://github.com/njasm/container)
|
||||
- [PHP-DI](http://php-di.org)
|
||||
- [Picotainer](https://github.com/thecodingmachine/picotainer)
|
||||
- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
|
||||
- [Pimple3-ContainerInterop](https://github.com/Sam-Burns/pimple3-containerinterop) (using Pimple v3)
|
||||
- [SitePoint Container](https://github.com/sitepoint/Container)
|
||||
- [Thruster Container](https://github.com/ThrusterIO/container) (PHP7 only)
|
||||
- [Ultra-Lite Container](https://github.com/ultra-lite/container)
|
||||
- [Unbox](https://github.com/mindplay-dk/unbox)
|
||||
- [XStatic](https://github.com/jeremeamia/xstatic)
|
||||
- [Zend\ServiceManager](https://github.com/zendframework/zend-servicemanager)
|
||||
- [Zit](https://github.com/inxilpro/Zit)
|
||||
|
||||
### Projects implementing the *delegate lookup* feature
|
||||
|
||||
- [Aura.Di](https://github.com/auraphp/Aura.Di)
|
||||
- [Burlap](https://github.com/codeeverything/burlap)
|
||||
- [Chernozem](https://github.com/pyrsmk/Chernozem)
|
||||
- [InDI](https://github.com/idealogica/indi)
|
||||
- [League/Container](http://container.thephpleague.com/)
|
||||
- [Mouf](http://mouf-php.com)
|
||||
- [Picotainer](https://github.com/thecodingmachine/picotainer)
|
||||
- [PHP-DI](http://php-di.org)
|
||||
- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
|
||||
- [Ultra-Lite Container](https://github.com/ultra-lite/container)
|
||||
|
||||
### Middlewares implementing `ContainerInterface`
|
||||
|
||||
- [Alias-Container](https://github.com/thecodingmachine/alias-container): add
|
||||
aliases support to any container
|
||||
- [Prefixer-Container](https://github.com/thecodingmachine/prefixer-container):
|
||||
dynamically prefix identifiers
|
||||
- [Lazy-Container](https://github.com/snapshotpl/lazy-container): lazy services
|
||||
|
||||
### Projects using `ContainerInterface`
|
||||
|
||||
The list below contains only a sample of all the projects consuming `ContainerInterface`. For a more complete list have a look [here](http://packanalyst.com/class?q=Interop%5CContainer%5CContainerInterface).
|
||||
|
||||
| | Downloads |
|
||||
| --- | --- |
|
||||
| [Adroit](https://github.com/bitexpert/adroit) |  |
|
||||
| [Behat](https://github.com/Behat/Behat/pull/974) |  |
|
||||
| [blast-facades](https://github.com/phpthinktank/blast-facades): Minimize complexity and represent dependencies as facades. |  |
|
||||
| [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di): an extension to [Silex](http://silex.sensiolabs.org/) that adds support for any *container-interop* compatible container |  |
|
||||
| [mindplay/walkway](https://github.com/mindplay-dk/walkway): a modular request router |  |
|
||||
| [mindplay/middleman](https://github.com/mindplay-dk/middleman): minimalist PSR-7 middleware dispatcher |  |
|
||||
| [PHP-DI/Invoker](https://github.com/PHP-DI/Invoker): extensible and configurable invoker/dispatcher |  |
|
||||
| [Prophiler](https://github.com/fabfuel/prophiler) |  |
|
||||
| [Silly](https://github.com/mnapoli/silly): CLI micro-framework |  |
|
||||
| [Slim v3](https://github.com/slimphp/Slim) |  |
|
||||
| [Splash](http://mouf-php.com/packages/mouf/mvc.splash-common/version/8.0-dev/README.md) |  |
|
||||
| [Woohoo Labs. Harmony](https://github.com/woohoolabs/harmony): a flexible micro-framework |  |
|
||||
| [zend-expressive](https://github.com/zendframework/zend-expressive) |  |
|
||||
|
||||
|
||||
## Workflow
|
||||
|
||||
Everyone is welcome to join and contribute.
|
||||
|
||||
The general workflow looks like this:
|
||||
|
||||
1. Someone opens a discussion (GitHub issue) to suggest an interface
|
||||
1. Feedback is gathered
|
||||
1. The interface is added to a development branch
|
||||
1. We release alpha versions so that the interface can be experimented with
|
||||
1. Discussions and edits ensue until the interface is deemed stable by a general consensus
|
||||
1. A new minor version of the package is released
|
||||
|
||||
We try to not break BC by creating new interfaces instead of editing existing ones.
|
||||
|
||||
While we currently work on interfaces, we are open to anything that might help towards interoperability, may that
|
||||
be code, best practices, etc.
|
15
system/vendor/container-interop/container-interop/composer.json
vendored
Normal file
15
system/vendor/container-interop/container-interop/composer.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"type": "library",
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"homepage": "https://github.com/container-interop/container-interop",
|
||||
"license": "MIT",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/Interop/Container/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0"
|
||||
}
|
||||
}
|
114
system/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md
vendored
Normal file
114
system/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
# ContainerInterface Meta Document
|
||||
|
||||
## Introduction
|
||||
|
||||
This document describes the process and discussions that lead to the `ContainerInterface`.
|
||||
Its goal is to explain the reasons behind each decision.
|
||||
|
||||
## Goal
|
||||
|
||||
The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
|
||||
container to obtain objects and parameters.
|
||||
|
||||
By standardizing such a behavior, frameworks and libraries using the `ContainerInterface`
|
||||
could work with any compatible container.
|
||||
That would allow end users to choose their own container based on their own preferences.
|
||||
|
||||
It is important to distinguish the two usages of a container:
|
||||
|
||||
- configuring entries
|
||||
- fetching entries
|
||||
|
||||
Most of the time, those two sides are not used by the same party.
|
||||
While it is often end users who tend to configure entries, it is generally the framework that fetch
|
||||
entries to build the application.
|
||||
|
||||
This is why this interface focuses only on how entries can be fetched from a container.
|
||||
|
||||
## Interface name
|
||||
|
||||
The interface name has been thoroughly discussed and was decided by a vote.
|
||||
|
||||
The list of options considered with their respective votes are:
|
||||
|
||||
- `ContainerInterface`: +8
|
||||
- `ProviderInterface`: +2
|
||||
- `LocatorInterface`: 0
|
||||
- `ReadableContainerInterface`: -5
|
||||
- `ServiceLocatorInterface`: -6
|
||||
- `ObjectFactory`: -6
|
||||
- `ObjectStore`: -8
|
||||
- `ConsumerInterface`: -9
|
||||
|
||||
[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
|
||||
|
||||
The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1).
|
||||
|
||||
## Interface methods
|
||||
|
||||
The choice of which methods the interface would contain was made after a statistical analysis of existing containers.
|
||||
The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681).
|
||||
|
||||
The summary of the analysis showed that:
|
||||
|
||||
- all containers offer a method to get an entry by its id
|
||||
- a large majority name such method `get()`
|
||||
- for all containers, the `get()` method has 1 mandatory parameter of type string
|
||||
- some containers have an optional additional argument for `get()`, but it doesn't have the same purpose between containers
|
||||
- a large majority of the containers offer a method to test if it can return an entry by its id
|
||||
- a majority name such method `has()`
|
||||
- for all containers offering `has()`, the method has exactly 1 parameter of type string
|
||||
- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()`
|
||||
- a large majority of the containers don't implement `ArrayAccess`
|
||||
|
||||
The question of whether to include methods to define entries has been discussed in
|
||||
[issue #1](https://github.com/container-interop/container-interop/issues/1).
|
||||
It has been judged that such methods do not belong in the interface described here because it is out of its scope
|
||||
(see the "Goal" section).
|
||||
|
||||
As a result, the `ContainerInterface` contains two methods:
|
||||
|
||||
- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found.
|
||||
- `has()`, returning a boolean, with one mandatory string parameter.
|
||||
|
||||
### Number of parameters in `get()` method
|
||||
|
||||
While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with
|
||||
existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters
|
||||
as long as they are optional, because the implementation *does* satisfy the interface.
|
||||
|
||||
This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6).
|
||||
|
||||
### Type of the `$id` parameter
|
||||
|
||||
The type of the `$id` parameter in `get()` and `has()` has been discussed in
|
||||
[issue #6](https://github.com/container-interop/container-interop/issues/6).
|
||||
While `string` is used in all the containers that were analyzed, it was suggested that allowing
|
||||
anything (such as objects) could allow containers to offer a more advanced query API.
|
||||
|
||||
An example given was to use the container as an object builder. The `$id` parameter would then be an
|
||||
object that would describe how to create an instance.
|
||||
|
||||
The conclusion of the discussion was that this was beyond the scope of getting entries from a container without
|
||||
knowing how the container provided them, and it was more fit for a factory.
|
||||
|
||||
## Contributors
|
||||
|
||||
Are listed here all people that contributed in the discussions or votes, by alphabetical order:
|
||||
|
||||
- [Amy Stephen](https://github.com/AmyStephen)
|
||||
- [David Négrier](https://github.com/moufmouf)
|
||||
- [Don Gilbert](https://github.com/dongilbert)
|
||||
- [Jason Judge](https://github.com/judgej)
|
||||
- [Jeremy Lindblom](https://github.com/jeremeamia)
|
||||
- [Marco Pivetta](https://github.com/Ocramius)
|
||||
- [Matthieu Napoli](https://github.com/mnapoli)
|
||||
- [Paul M. Jones](https://github.com/pmjones)
|
||||
- [Stephan Hochdörfer](https://github.com/shochdoerfer)
|
||||
- [Taylor Otwell](https://github.com/taylorotwell)
|
||||
|
||||
## Relevant links
|
||||
|
||||
- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php)
|
||||
- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed)
|
||||
- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
|
158
system/vendor/container-interop/container-interop/docs/ContainerInterface.md
vendored
Normal file
158
system/vendor/container-interop/container-interop/docs/ContainerInterface.md
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
Container interface
|
||||
===================
|
||||
|
||||
This document describes a common interface for dependency injection containers.
|
||||
|
||||
The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
|
||||
container to obtain objects and parameters (called *entries* in the rest of this document).
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||
interpreted as described in [RFC 2119][].
|
||||
|
||||
The word `implementor` in this document is to be interpreted as someone
|
||||
implementing the `ContainerInterface` in a dependency injection-related library or framework.
|
||||
Users of dependency injections containers (DIC) are referred to as `user`.
|
||||
|
||||
[RFC 2119]: http://tools.ietf.org/html/rfc2119
|
||||
|
||||
1. Specification
|
||||
-----------------
|
||||
|
||||
### 1.1 Basics
|
||||
|
||||
- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`.
|
||||
|
||||
- `get` takes one mandatory parameter: an entry identifier. It MUST be a string.
|
||||
A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier
|
||||
is not known to the container. Two successive calls to `get` with the same
|
||||
identifier SHOULD return the same value. However, depending on the `implementor`
|
||||
design and/or `user` configuration, different values might be returned, so
|
||||
`user` SHOULD NOT rely on getting the same value on 2 successive calls.
|
||||
While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations
|
||||
MAY accept additional optional parameters.
|
||||
|
||||
- `has` takes one unique parameter: an entry identifier. It MUST return `true`
|
||||
if an entry identifier is known to the container and `false` if it is not.
|
||||
`has($id)` returning true does not mean that `get($id)` will not throw an exception.
|
||||
It does however mean that `get($id)` will not throw a `NotFoundException`.
|
||||
|
||||
### 1.2 Exceptions
|
||||
|
||||
Exceptions directly thrown by the container MUST implement the
|
||||
[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php).
|
||||
|
||||
A call to the `get` method with a non-existing id SHOULD throw a
|
||||
[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php).
|
||||
|
||||
### 1.3 Additional features
|
||||
|
||||
This section describes additional features that MAY be added to a container. Containers are not
|
||||
required to implement these features to respect the ContainerInterface.
|
||||
|
||||
#### 1.3.1 Delegate lookup feature
|
||||
|
||||
The goal of the *delegate lookup* feature is to allow several containers to share entries.
|
||||
Containers implementing this feature can perform dependency lookups in other containers.
|
||||
|
||||
Containers implementing this feature will offer a greater lever of interoperability
|
||||
with other containers. Implementation of this feature is therefore RECOMMENDED.
|
||||
|
||||
A container implementing this feature:
|
||||
|
||||
- MUST implement the `ContainerInterface`
|
||||
- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
|
||||
or any possible way). The delegate container MUST implement the `ContainerInterface`.
|
||||
|
||||
When a container is configured to use a delegate container for dependencies:
|
||||
|
||||
- Calls to the `get` method should only return an entry if the entry is part of the container.
|
||||
If the entry is not part of the container, an exception should be thrown
|
||||
(as requested by the `ContainerInterface`).
|
||||
- Calls to the `has` method should only return `true` if the entry is part of the container.
|
||||
If the entry is not part of the container, `false` should be returned.
|
||||
- If the fetched entry has dependencies, **instead** of performing
|
||||
the dependency lookup in the container, the lookup is performed on the *delegate container*.
|
||||
|
||||
Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
|
||||
|
||||
It is however allowed for containers to provide exception cases for special entries, and a way to lookup
|
||||
into the same container (or another container) instead of the delegate container.
|
||||
|
||||
2. Package
|
||||
----------
|
||||
|
||||
The interfaces and classes described as well as relevant exception are provided as part of the
|
||||
[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package.
|
||||
|
||||
3. `Interop\Container\ContainerInterface`
|
||||
-----------------------------------------
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace Interop\Container;
|
||||
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use Interop\Container\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
* Describes the interface of a container that exposes methods to read its entries.
|
||||
*/
|
||||
interface ContainerInterface
|
||||
{
|
||||
/**
|
||||
* Finds an entry of the container by its identifier and returns it.
|
||||
*
|
||||
* @param string $id Identifier of the entry to look for.
|
||||
*
|
||||
* @throws NotFoundException No entry was found for this identifier.
|
||||
* @throws ContainerException Error while retrieving the entry.
|
||||
*
|
||||
* @return mixed Entry.
|
||||
*/
|
||||
public function get($id);
|
||||
|
||||
/**
|
||||
* Returns true if the container can return an entry for the given identifier.
|
||||
* Returns false otherwise.
|
||||
*
|
||||
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
|
||||
* It does however mean that `get($id)` will not throw a `NotFoundException`.
|
||||
*
|
||||
* @param string $id Identifier of the entry to look for.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($id);
|
||||
}
|
||||
```
|
||||
|
||||
4. `Interop\Container\Exception\ContainerException`
|
||||
---------------------------------------------------
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace Interop\Container\Exception;
|
||||
|
||||
/**
|
||||
* Base interface representing a generic exception in a container.
|
||||
*/
|
||||
interface ContainerException
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
5. `Interop\Container\Exception\NotFoundException`
|
||||
---------------------------------------------------
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace Interop\Container\Exception;
|
||||
|
||||
/**
|
||||
* No entry was found in the container.
|
||||
*/
|
||||
interface NotFoundException extends ContainerException
|
||||
{
|
||||
}
|
||||
```
|
259
system/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
vendored
Normal file
259
system/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
Delegate lookup feature Meta Document
|
||||
=====================================
|
||||
|
||||
1. Summary
|
||||
----------
|
||||
|
||||
This document describes the *delegate lookup feature*.
|
||||
Containers are not required to implement this feature to respect the `ContainerInterface`.
|
||||
However, containers implementing this feature will offer a greater lever of interoperability
|
||||
with other containers, allowing multiple containers to share entries in the same application.
|
||||
Implementation of this feature is therefore recommanded.
|
||||
|
||||
2. Why Bother?
|
||||
--------------
|
||||
|
||||
The [`ContainerInterface`](../src/Interop/Container/ContainerInterface.php) ([meta doc](ContainerInterface.md))
|
||||
standardizes how frameworks and libraries make use of a container to obtain objects and parameters.
|
||||
|
||||
By standardizing such a behavior, frameworks and libraries relying on the `ContainerInterface`
|
||||
could work with any compatible container.
|
||||
That would allow end users to choose their own container based on their own preferences.
|
||||
|
||||
The `ContainerInterface` is also enough if we want to have several containers side-by-side in the same
|
||||
application. For instance, this is what the [CompositeContainer](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php)
|
||||
class of [Acclimate](https://github.com/jeremeamia/acclimate-container) is designed for:
|
||||
|
||||

|
||||
|
||||
However, an instance in container 1 cannot reference an instance in container 2.
|
||||
|
||||
It would be better if an instance of container 1 could reference an instance in container 2,
|
||||
and the opposite should be true.
|
||||
|
||||

|
||||
|
||||
In the sample above, entry 1 in container 1 is referencing entry 3 in container 2.
|
||||
|
||||
3. Scope
|
||||
--------
|
||||
|
||||
### 3.1 Goals
|
||||
|
||||
The goal of the *delegate lookup* feature is to allow several containers to share entries.
|
||||
|
||||
4. Approaches
|
||||
-------------
|
||||
|
||||
### 4.1 Chosen Approach
|
||||
|
||||
Containers implementing this feature can perform dependency lookups in other containers.
|
||||
|
||||
A container implementing this feature:
|
||||
|
||||
- must implement the `ContainerInterface`
|
||||
- must provide a way to register a *delegate container* (using a constructor parameter, or a setter, or any
|
||||
possible way). The *delegate container* must implement the `ContainerInterface`.
|
||||
|
||||
When a *delegate container* is configured on a container:
|
||||
|
||||
- Calls to the `get` method should only return an entry if the entry is part of the container.
|
||||
If the entry is not part of the container, an exception should be thrown (as required in the `ContainerInterface`).
|
||||
- Calls to the `has` method should only return *true* if the entry is part of the container.
|
||||
If the entry is not part of the container, *false* should be returned.
|
||||
- Finally, the important part: if the entry we are fetching has dependencies,
|
||||
**instead** of perfoming the dependency lookup in the container, the lookup is performed on the *delegate container*.
|
||||
|
||||
Important! By default, the lookup should be performed on the delegate container **only**, not on the container itself.
|
||||
|
||||
It is however allowed for containers to provide exception cases for special entries, and a way to lookup into
|
||||
the same container (or another container) instead of the delegate container.
|
||||
|
||||
### 4.2 Typical usage
|
||||
|
||||
The *delegate container* will usually be a composite container. A composite container is a container that
|
||||
contains several other containers. When performing a lookup on a composite container, the inner containers are
|
||||
queried until one container returns an entry.
|
||||
An inner container implementing the *delegate lookup feature* will return entries it contains, but if these
|
||||
entries have dependencies, the dependencies lookup calls will be performed on the composite container, giving
|
||||
a chance to all containers to answer.
|
||||
|
||||
Interestingly enough, the order in which containers are added in the composite container matters. Indeed,
|
||||
the first containers to be added in the composite container can "override" the entries of containers with
|
||||
lower priority.
|
||||
|
||||

|
||||
|
||||
In the example above, "container 2" contains a controller "myController" and the controller is referencing an
|
||||
"entityManager" entry. "Container 1" contains also an entry named "entityManager".
|
||||
Without the *delegate lookup* feature, when requesting the "myController" instance to container 2, it would take
|
||||
in charge the instanciation of both entries.
|
||||
|
||||
However, using the *delegate lookup* feature, here is what happens when we ask the composite container for the
|
||||
"myController" instance:
|
||||
|
||||
- The composite container asks container 1 if if contains the "myController" instance. The answer is no.
|
||||
- The composite container asks container 2 if if contains the "myController" instance. The answer is yes.
|
||||
- The composite container performs a `get` call on container 2 for the "myController" instance.
|
||||
- Container 2 sees that "myController" has a dependency on "entityManager".
|
||||
- Container 2 delegates the lookup of "entityManager" to the composite container.
|
||||
- The composite container asks container 1 if if contains the "entityManager" instance. The answer is yes.
|
||||
- The composite container performs a `get` call on container 1 for the "entityManager" instance.
|
||||
|
||||
In the end, we get a controller instanciated by container 2 that references an entityManager instanciated
|
||||
by container 1.
|
||||
|
||||
### 4.3 Alternative: the fallback strategy
|
||||
|
||||
The first proposed approach we tried was to perform all the lookups in the "local" container,
|
||||
and if a lookup fails in the container, to use the delegate container. In this scenario, the
|
||||
delegate container is used in "fallback" mode.
|
||||
|
||||
This strategy has been described in @moufmouf blog post: http://mouf-php.com/container-interop-whats-next (solution 1).
|
||||
It was also discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-33570697) and
|
||||
[here](https://github.com/container-interop/container-interop/pull/20#issuecomment-56599631).
|
||||
|
||||
Problems with this strategy:
|
||||
|
||||
- Heavy problem regarding infinite loops
|
||||
- Unable to overload a container entry with the delegate container entry
|
||||
|
||||
### 4.4 Alternative: force implementing an interface
|
||||
|
||||
The first proposed approach was to develop a `ParentAwareContainerInterface` interface.
|
||||
It was proposed here: https://github.com/container-interop/container-interop/pull/8
|
||||
|
||||
The interface would have had the behaviour of the delegate lookup feature but would have forced the addition of
|
||||
a `setParentContainter` method:
|
||||
|
||||
```php
|
||||
interface ParentAwareContainerInterface extends ReadableContainerInterface {
|
||||
/**
|
||||
* Sets the parent container associated to that container. This container will call
|
||||
* the parent container to fetch dependencies.
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function setParentContainer(ContainerInterface $container);
|
||||
}
|
||||
```
|
||||
|
||||
The interface idea was first questioned by @Ocramius [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
|
||||
@Ocramius expressed the idea that an interface should not contain setters, otherwise, it is forcing implementation
|
||||
details on the class implementing the interface.
|
||||
Then @mnapoli made a proposal for a "convention" [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51841079),
|
||||
this idea was further discussed until all participants in the discussion agreed to remove the interface idea
|
||||
and replace it with a "standard" feature.
|
||||
|
||||
**Pros:**
|
||||
|
||||
If we had had an interface, we could have delegated the registration of the delegate/composite container to the
|
||||
the delegate/composite container itself.
|
||||
For instance:
|
||||
|
||||
```php
|
||||
$containerA = new ContainerA();
|
||||
$containerB = new ContainerB();
|
||||
|
||||
$compositeContainer = new CompositeContainer([$containerA, $containerB]);
|
||||
|
||||
// The call to 'setParentContainer' is delegated to the CompositeContainer
|
||||
// It is not the responsibility of the user anymore.
|
||||
class CompositeContainer {
|
||||
...
|
||||
|
||||
public function __construct($containers) {
|
||||
foreach ($containers as $container) {
|
||||
if ($container instanceof ParentAwareContainerInterface) {
|
||||
$container->setParentContainer($this);
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**Cons:**
|
||||
|
||||
Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
|
||||
Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments,
|
||||
and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface.
|
||||
|
||||
### 4.4 Alternative: no exception case for delegate lookups
|
||||
|
||||
Originally, the proposed wording for delegate lookup calls was:
|
||||
|
||||
> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself.
|
||||
|
||||
This was later replaced by:
|
||||
|
||||
> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
|
||||
>
|
||||
> It is however allowed for containers to provide exception cases for special entries, and a way to lookup
|
||||
> into the same container (or another container) instead of the delegate container.
|
||||
|
||||
Exception cases have been allowed to avoid breaking dependencies with some services that must be provided
|
||||
by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235
|
||||
|
||||
### 4.5 Alternative: having one of the containers act as the composite container
|
||||
|
||||
In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to
|
||||
add another DI container to this container. Most of the time, the "big" framework will be responsible for
|
||||
creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted,
|
||||
the "big" framework will not be aware of the existence of a composite container that it should use instead
|
||||
of its own container.
|
||||
|
||||
For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container
|
||||
to make it act as a composite container.
|
||||
|
||||
This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194)
|
||||
and [here](http://mouf-php.com/container-interop-whats-next#solution4).
|
||||
|
||||
This was implemented in Symfony 2 using:
|
||||
|
||||
- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0)
|
||||
- [framework interop](https://github.com/mnapoli/framework-interop/)
|
||||
|
||||
This was implemented in Silex using:
|
||||
|
||||
- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
|
||||
|
||||
Having a container act as the composite container is not part of the delegate lookup standard because it is
|
||||
simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop
|
||||
play nice with other DI containers.
|
||||
|
||||
|
||||
5. Implementations
|
||||
------------------
|
||||
|
||||
The following projects already implement the delegate lookup feature:
|
||||
|
||||
- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120)
|
||||
- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72)
|
||||
- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62)
|
||||
|
||||
6. People
|
||||
---------
|
||||
|
||||
Are listed here all people that contributed in the discussions, by alphabetical order:
|
||||
|
||||
- [Alexandru Pătrănescu](https://github.com/drealecs)
|
||||
- [Ben Peachey](https://github.com/potherca)
|
||||
- [David Négrier](https://github.com/moufmouf)
|
||||
- [Jeremy Lindblom](https://github.com/jeremeamia)
|
||||
- [Marco Pivetta](https://github.com/Ocramius)
|
||||
- [Matthieu Napoli](https://github.com/mnapoli)
|
||||
- [Nelson J Morais](https://github.com/njasm)
|
||||
- [Phil Sturgeon](https://github.com/philsturgeon)
|
||||
- [Stephan Hochdörfer](https://github.com/shochdoerfer)
|
||||
|
||||
7. Relevant Links
|
||||
-----------------
|
||||
|
||||
_**Note:** Order descending chronologically._
|
||||
|
||||
- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20)
|
||||
- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8)
|
||||
- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next)
|
||||
|
60
system/vendor/container-interop/container-interop/docs/Delegate-lookup.md
vendored
Normal file
60
system/vendor/container-interop/container-interop/docs/Delegate-lookup.md
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
Delegate lookup feature
|
||||
=======================
|
||||
|
||||
This document describes a standard for dependency injection containers.
|
||||
|
||||
The goal set by the *delegate lookup* feature is to allow several containers to share entries.
|
||||
Containers implementing this feature can perform dependency lookups in other containers.
|
||||
|
||||
Containers implementing this feature will offer a greater lever of interoperability
|
||||
with other containers. Implementation of this feature is therefore RECOMMENDED.
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
||||
interpreted as described in [RFC 2119][].
|
||||
|
||||
The word `implementor` in this document is to be interpreted as someone
|
||||
implementing the delegate lookup feature in a dependency injection-related library or framework.
|
||||
Users of dependency injections containers (DIC) are referred to as `user`.
|
||||
|
||||
[RFC 2119]: http://tools.ietf.org/html/rfc2119
|
||||
|
||||
1. Vocabulary
|
||||
-------------
|
||||
|
||||
In a dependency injection container, the container is used to fetch entries.
|
||||
Entries can have dependencies on other entries. Usually, these other entries are fetched by the container.
|
||||
|
||||
The *delegate lookup* feature is the ability for a container to fetch dependencies in
|
||||
another container. In the rest of the document, the word "container" will reference the container
|
||||
implemented by the implementor. The word "delegate container" will reference the container we are
|
||||
fetching the dependencies from.
|
||||
|
||||
2. Specification
|
||||
----------------
|
||||
|
||||
A container implementing the *delegate lookup* feature:
|
||||
|
||||
- MUST implement the [`ContainerInterface`](ContainerInterface.md)
|
||||
- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
|
||||
or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md).
|
||||
|
||||
When a container is configured to use a delegate container for dependencies:
|
||||
|
||||
- Calls to the `get` method should only return an entry if the entry is part of the container.
|
||||
If the entry is not part of the container, an exception should be thrown
|
||||
(as requested by the [`ContainerInterface`](ContainerInterface.md)).
|
||||
- Calls to the `has` method should only return `true` if the entry is part of the container.
|
||||
If the entry is not part of the container, `false` should be returned.
|
||||
- If the fetched entry has dependencies, **instead** of performing
|
||||
the dependency lookup in the container, the lookup is performed on the *delegate container*.
|
||||
|
||||
Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself.
|
||||
|
||||
It is however allowed for containers to provide exception cases for special entries, and a way to lookup
|
||||
into the same container (or another container) instead of the delegate container.
|
||||
|
||||
3. Package / Interface
|
||||
----------------------
|
||||
|
||||
This feature is not tied to any code, interface or package.
|
BIN
system/vendor/container-interop/container-interop/docs/images/interoperating_containers.png
vendored
Normal file
BIN
system/vendor/container-interop/container-interop/docs/images/interoperating_containers.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
system/vendor/container-interop/container-interop/docs/images/priority.png
vendored
Normal file
BIN
system/vendor/container-interop/container-interop/docs/images/priority.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
system/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png
vendored
Normal file
BIN
system/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
15
system/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php
vendored
Normal file
15
system/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
|
||||
*/
|
||||
|
||||
namespace Interop\Container;
|
||||
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
|
||||
/**
|
||||
* Describes the interface of a container that exposes methods to read its entries.
|
||||
*/
|
||||
interface ContainerInterface extends PsrContainerInterface
|
||||
{
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
|
||||
*/
|
||||
|
||||
namespace Interop\Container\Exception;
|
||||
|
||||
use Psr\Container\ContainerExceptionInterface as PsrContainerException;
|
||||
|
||||
/**
|
||||
* Base interface representing a generic exception in a container.
|
||||
*/
|
||||
interface ContainerException extends PsrContainerException
|
||||
{
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
|
||||
*/
|
||||
|
||||
namespace Interop\Container\Exception;
|
||||
|
||||
use Psr\Container\NotFoundExceptionInterface as PsrNotFoundException;
|
||||
|
||||
/**
|
||||
* No entry was found in the container.
|
||||
*/
|
||||
interface NotFoundException extends ContainerException, PsrNotFoundException
|
||||
{
|
||||
}
|
1
system/vendor/erusev/parsedown
vendored
Submodule
1
system/vendor/erusev/parsedown
vendored
Submodule
Submodule system/vendor/erusev/parsedown added at 1bf24f7334
1
system/vendor/erusev/parsedown-extra
vendored
Submodule
1
system/vendor/erusev/parsedown-extra
vendored
Submodule
Submodule system/vendor/erusev/parsedown-extra added at 0db5cce735
1
system/vendor/jbroadway/urlify
vendored
Submodule
1
system/vendor/jbroadway/urlify
vendored
Submodule
Submodule system/vendor/jbroadway/urlify added at 99bb78cd90
5
system/vendor/nikic/fast-route/.gitignore
vendored
Normal file
5
system/vendor/nikic/fast-route/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/vendor/
|
||||
.idea/
|
||||
|
||||
# ignore lock file since we have no extra dependencies
|
||||
composer.lock
|
1
system/vendor/nikic/fast-route/.hhconfig
vendored
Normal file
1
system/vendor/nikic/fast-route/.hhconfig
vendored
Normal file
@@ -0,0 +1 @@
|
||||
assume_php=false
|
12
system/vendor/nikic/fast-route/.travis.yml
vendored
Normal file
12
system/vendor/nikic/fast-route/.travis.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: 7.0
|
126
system/vendor/nikic/fast-route/FastRoute.hhi
vendored
Normal file
126
system/vendor/nikic/fast-route/FastRoute.hhi
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<?hh // decl
|
||||
|
||||
namespace FastRoute {
|
||||
class BadRouteException extends \LogicException {
|
||||
}
|
||||
|
||||
interface RouteParser {
|
||||
public function parse(string $route): array<array>;
|
||||
}
|
||||
|
||||
class RouteCollector {
|
||||
public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator);
|
||||
public function addRoute(mixed $httpMethod, string $route, mixed $handler): void;
|
||||
public function getData(): array;
|
||||
}
|
||||
|
||||
class Route {
|
||||
public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables);
|
||||
public function matches(string $str): bool;
|
||||
}
|
||||
|
||||
interface DataGenerator {
|
||||
public function addRoute(string $httpMethod, array $routeData, mixed $handler);
|
||||
public function getData(): array;
|
||||
}
|
||||
|
||||
interface Dispatcher {
|
||||
const int NOT_FOUND = 0;
|
||||
const int FOUND = 1;
|
||||
const int METHOD_NOT_ALLOWED = 2;
|
||||
public function dispatch(string $httpMethod, string $uri): array;
|
||||
}
|
||||
|
||||
function simpleDispatcher(
|
||||
(function(RouteCollector): void) $routeDefinitionCallback,
|
||||
shape(
|
||||
'routeParser' => ?classname<RouteParser>,
|
||||
'dataGenerator' => ?classname<DataGenerator>,
|
||||
'dispatcher' => ?classname<Dispatcher>,
|
||||
'routeCollector' => ?classname<RouteCollector>,
|
||||
) $options = shape()): Dispatcher;
|
||||
|
||||
function cachedDispatcher(
|
||||
(function(RouteCollector): void) $routeDefinitionCallback,
|
||||
shape(
|
||||
'routeParser' => ?classname<RouteParser>,
|
||||
'dataGenerator' => ?classname<DataGenerator>,
|
||||
'dispatcher' => ?classname<Dispatcher>,
|
||||
'routeCollector' => ?classname<RouteCollector>,
|
||||
'cacheDisabled' => ?bool,
|
||||
'cacheFile' => ?string,
|
||||
) $options = shape()): Dispatcher;
|
||||
}
|
||||
|
||||
namespace FastRoute\DataGenerator {
|
||||
abstract class RegexBasedAbstract implements \FastRoute\DataGenerator {
|
||||
protected abstract function getApproxChunkSize();
|
||||
protected abstract function processChunk($regexToRoutesMap);
|
||||
|
||||
public function addRoute(string $httpMethod, array $routeData, mixed $handler): void;
|
||||
public function getData(): array;
|
||||
}
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
|
||||
class MarkBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize(): int;
|
||||
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FastRoute\Dispatcher {
|
||||
abstract class RegexBasedAbstract implements \FastRoute\Dispatcher {
|
||||
protected abstract function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
|
||||
public function dispatch(string $httpMethod, string $uri): array;
|
||||
}
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
|
||||
class MarkBased extends RegexBasedAbstract {
|
||||
public function __construct(array $data);
|
||||
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FastRoute\RouteParser {
|
||||
class Std implements \FastRoute\RouteParser {
|
||||
const string VARIABLE_REGEX = <<<'REGEX'
|
||||
\{
|
||||
\s* ([a-zA-Z][a-zA-Z0-9_]*) \s*
|
||||
(?:
|
||||
: \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
|
||||
)?
|
||||
\}
|
||||
REGEX;
|
||||
const string DEFAULT_DISPATCH_REGEX = '[^/]+';
|
||||
public function parse(string $route): array<array>;
|
||||
}
|
||||
}
|
31
system/vendor/nikic/fast-route/LICENSE
vendored
Normal file
31
system/vendor/nikic/fast-route/LICENSE
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
Copyright (c) 2013 by Nikita Popov.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
313
system/vendor/nikic/fast-route/README.md
vendored
Normal file
313
system/vendor/nikic/fast-route/README.md
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
FastRoute - Fast request router for PHP
|
||||
=======================================
|
||||
|
||||
This library provides a fast implementation of a regular expression based router. [Blog post explaining how the
|
||||
implementation works and why it is fast.][blog_post]
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
To install with composer:
|
||||
|
||||
```sh
|
||||
composer require nikic/fast-route
|
||||
```
|
||||
|
||||
Requires PHP 5.4 or newer.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Here's a basic usage example:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require '/path/to/vendor/autoload.php';
|
||||
|
||||
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
|
||||
$r->addRoute('GET', '/users', 'get_all_users_handler');
|
||||
// {id} must be a number (\d+)
|
||||
$r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler');
|
||||
// The /{title} suffix is optional
|
||||
$r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler');
|
||||
});
|
||||
|
||||
// Fetch method and URI from somewhere
|
||||
$httpMethod = $_SERVER['REQUEST_METHOD'];
|
||||
$uri = $_SERVER['REQUEST_URI'];
|
||||
|
||||
// Strip query string (?foo=bar) and decode URI
|
||||
if (false !== $pos = strpos($uri, '?')) {
|
||||
$uri = substr($uri, 0, $pos);
|
||||
}
|
||||
$uri = rawurldecode($uri);
|
||||
|
||||
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
|
||||
switch ($routeInfo[0]) {
|
||||
case FastRoute\Dispatcher::NOT_FOUND:
|
||||
// ... 404 Not Found
|
||||
break;
|
||||
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
|
||||
$allowedMethods = $routeInfo[1];
|
||||
// ... 405 Method Not Allowed
|
||||
break;
|
||||
case FastRoute\Dispatcher::FOUND:
|
||||
$handler = $routeInfo[1];
|
||||
$vars = $routeInfo[2];
|
||||
// ... call $handler with $vars
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
### Defining routes
|
||||
|
||||
The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts
|
||||
a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling
|
||||
`addRoute()` on the collector instance:
|
||||
|
||||
```php
|
||||
$r->addRoute($method, $routePattern, $handler);
|
||||
```
|
||||
|
||||
The `$method` is an uppercase HTTP method string for which a certain route should match. It
|
||||
is possible to specify multiple valid methods using an array:
|
||||
|
||||
```php
|
||||
// These two calls
|
||||
$r->addRoute('GET', '/test', 'handler');
|
||||
$r->addRoute('POST', '/test', 'handler');
|
||||
// Are equivalent to this one call
|
||||
$r->addRoute(['GET', 'POST'], '/test', 'handler');
|
||||
```
|
||||
|
||||
By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo`
|
||||
and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify
|
||||
a custom pattern by writing `{bar:[0-9]+}`. Some examples:
|
||||
|
||||
```php
|
||||
// Matches /user/42, but not /user/xyz
|
||||
$r->addRoute('GET', '/user/{id:\d+}', 'handler');
|
||||
|
||||
// Matches /user/foobar, but not /user/foo/bar
|
||||
$r->addRoute('GET', '/user/{name}', 'handler');
|
||||
|
||||
// Matches /user/foo/bar as well
|
||||
$r->addRoute('GET', '/user/{name:.+}', 'handler');
|
||||
```
|
||||
|
||||
Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}`
|
||||
is not a valid placeholder, because `()` is a capturing group. Instead you can use either
|
||||
`{lang:en|de}` or `{lang:(?:en|de)}`.
|
||||
|
||||
Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]`
|
||||
will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position,
|
||||
not in the middle of a route.
|
||||
|
||||
```php
|
||||
// This route
|
||||
$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler');
|
||||
// Is equivalent to these two routes
|
||||
$r->addRoute('GET', '/user/{id:\d+}', 'handler');
|
||||
$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler');
|
||||
|
||||
// Multiple nested optional parts are possible as well
|
||||
$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler');
|
||||
|
||||
// This route is NOT valid, because optional parts can only occur at the end
|
||||
$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler');
|
||||
```
|
||||
|
||||
The `$handler` parameter does not necessarily have to be a callback, it could also be a controller
|
||||
class name or any other kind of data you wish to associate with the route. FastRoute only tells you
|
||||
which handler corresponds to your URI, how you interpret it is up to you.
|
||||
|
||||
#### Shorcut methods for common request methods
|
||||
|
||||
For the `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `HEAD` request methods shortcut methods are available. For example:
|
||||
|
||||
```php
|
||||
$r->get('/get-route', 'get_handler');
|
||||
$r->post('/post-route', 'post_handler');
|
||||
```
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
```php
|
||||
$r->addRoute('GET', '/get-route', 'get_handler');
|
||||
$r->addRoute('POST', '/post-route', 'post_handler');
|
||||
```
|
||||
|
||||
#### Route Groups
|
||||
|
||||
Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix.
|
||||
|
||||
For example, defining your routes as:
|
||||
|
||||
```php
|
||||
$r->addGroup('/admin', function (RouteCollector $r) {
|
||||
$r->addRoute('GET', '/do-something', 'handler');
|
||||
$r->addRoute('GET', '/do-another-thing', 'handler');
|
||||
$r->addRoute('GET', '/do-something-else', 'handler');
|
||||
});
|
||||
```
|
||||
|
||||
Will have the same result as:
|
||||
|
||||
```php
|
||||
$r->addRoute('GET', '/admin/do-something', 'handler');
|
||||
$r->addRoute('GET', '/admin/do-another-thing', 'handler');
|
||||
$r->addRoute('GET', '/admin/do-something-else', 'handler');
|
||||
```
|
||||
|
||||
Nested groups are also supported, in which case the prefixes of all the nested groups are combined.
|
||||
|
||||
### Caching
|
||||
|
||||
The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless
|
||||
caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated
|
||||
routing data and construct the dispatcher from the cached information:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$dispatcher = FastRoute\cachedDispatcher(function(FastRoute\RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/user/{name}', 'handler2');
|
||||
}, [
|
||||
'cacheFile' => __DIR__ . '/route.cache', /* required */
|
||||
'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */
|
||||
]);
|
||||
```
|
||||
|
||||
The second parameter to the function is an options array, which can be used to specify the cache
|
||||
file location, among other things.
|
||||
|
||||
### Dispatching a URI
|
||||
|
||||
A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method
|
||||
accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them
|
||||
appropriately) is your job - this library is not bound to the PHP web SAPIs.
|
||||
|
||||
The `dispatch()` method returns an array whose first element contains a status code. It is one
|
||||
of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the
|
||||
method not allowed status the second array element contains a list of HTTP methods allowed for
|
||||
the supplied URI. For example:
|
||||
|
||||
[FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']]
|
||||
|
||||
> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the
|
||||
`Allow:` header to detail available methods for the requested resource. Applications using FastRoute
|
||||
should use the second array element to add this header when relaying a 405 response.
|
||||
|
||||
For the found status the second array element is the handler that was associated with the route
|
||||
and the third array element is a dictionary of placeholder names to their values. For example:
|
||||
|
||||
/* Routing against GET /user/nikic/42 */
|
||||
|
||||
[FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']]
|
||||
|
||||
### Overriding the route parser and dispatcher
|
||||
|
||||
The routing process makes use of three components: A route parser, a data generator and a
|
||||
dispatcher. The three components adhere to the following interfaces:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface RouteParser {
|
||||
public function parse($route);
|
||||
}
|
||||
|
||||
interface DataGenerator {
|
||||
public function addRoute($httpMethod, $routeData, $handler);
|
||||
public function getData();
|
||||
}
|
||||
|
||||
interface Dispatcher {
|
||||
const NOT_FOUND = 0, FOUND = 1, METHOD_NOT_ALLOWED = 2;
|
||||
|
||||
public function dispatch($httpMethod, $uri);
|
||||
}
|
||||
```
|
||||
|
||||
The route parser takes a route pattern string and converts it into an array of route infos, where
|
||||
each route info is again an array of it's parts. The structure is best understood using an example:
|
||||
|
||||
/* The route /user/{id:\d+}[/{name}] converts to the following array: */
|
||||
[
|
||||
[
|
||||
'/user/',
|
||||
['id', '\d+'],
|
||||
],
|
||||
[
|
||||
'/user/',
|
||||
['id', '\d+'],
|
||||
'/',
|
||||
['name', '[^/]+'],
|
||||
],
|
||||
]
|
||||
|
||||
This array can then be passed to the `addRoute()` method of a data generator. After all routes have
|
||||
been added the `getData()` of the generator is invoked, which returns all the routing data required
|
||||
by the dispatcher. The format of this data is not further specified - it is tightly coupled to
|
||||
the corresponding dispatcher.
|
||||
|
||||
The dispatcher accepts the routing data via a constructor and provides a `dispatch()` method, which
|
||||
you're already familiar with.
|
||||
|
||||
The route parser can be overwritten individually (to make use of some different pattern syntax),
|
||||
however the data generator and dispatcher should always be changed as a pair, as the output from
|
||||
the former is tightly coupled to the input of the latter. The reason the generator and the
|
||||
dispatcher are separate is that only the latter is needed when using caching (as the output of
|
||||
the former is what is being cached.)
|
||||
|
||||
When using the `simpleDispatcher` / `cachedDispatcher` functions from above the override happens
|
||||
through the options array:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
|
||||
/* ... */
|
||||
}, [
|
||||
'routeParser' => 'FastRoute\\RouteParser\\Std',
|
||||
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
|
||||
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
|
||||
]);
|
||||
```
|
||||
|
||||
The above options array corresponds to the defaults. By replacing `GroupCountBased` by
|
||||
`GroupPosBased` you could switch to a different dispatching strategy.
|
||||
|
||||
### A Note on HEAD Requests
|
||||
|
||||
The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]:
|
||||
|
||||
> The methods GET and HEAD MUST be supported by all general-purpose servers
|
||||
|
||||
To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an
|
||||
available GET route for a given resource. The PHP web SAPI transparently removes the entity body
|
||||
from HEAD responses so this behavior has no effect on the vast majority of users.
|
||||
|
||||
However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST
|
||||
NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is
|
||||
*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases.
|
||||
|
||||
Finally, note that applications MAY always specify their own HEAD method route for a given
|
||||
resource to bypass this behavior entirely.
|
||||
|
||||
### Credits
|
||||
|
||||
This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server.
|
||||
|
||||
A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey].
|
||||
|
||||
|
||||
[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1"
|
||||
[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html
|
||||
[levi]: https://github.com/morrisonlevi
|
||||
[rdlowrey]: https://github.com/rdlowrey
|
21
system/vendor/nikic/fast-route/composer.json
vendored
Normal file
21
system/vendor/nikic/fast-route/composer.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": ["routing", "router"],
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": ["src/functions.php"]
|
||||
}
|
||||
}
|
24
system/vendor/nikic/fast-route/phpunit.xml
vendored
Normal file
24
system/vendor/nikic/fast-route/phpunit.xml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="FastRoute Tests">
|
||||
<directory>./test/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
6
system/vendor/nikic/fast-route/src/BadRouteException.php
vendored
Normal file
6
system/vendor/nikic/fast-route/src/BadRouteException.php
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class BadRouteException extends \LogicException {
|
||||
}
|
25
system/vendor/nikic/fast-route/src/DataGenerator.php
vendored
Normal file
25
system/vendor/nikic/fast-route/src/DataGenerator.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface DataGenerator {
|
||||
/**
|
||||
* Adds a route to the data generator. The route data uses the
|
||||
* same format that is returned by RouterParser::parser().
|
||||
*
|
||||
* The handler doesn't necessarily need to be a callable, it
|
||||
* can be arbitrary data that will be returned when the route
|
||||
* matches.
|
||||
*
|
||||
* @param string $httpMethod
|
||||
* @param array $routeData
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function addRoute($httpMethod, $routeData, $handler);
|
||||
|
||||
/**
|
||||
* Returns dispatcher data in some unspecified format, which
|
||||
* depends on the used method of dispatch.
|
||||
*/
|
||||
public function getData();
|
||||
}
|
28
system/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php
vendored
Normal file
28
system/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize() {
|
||||
return 30;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap) {
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
|
||||
$suffixLen = 0;
|
||||
$suffix = '';
|
||||
$count = count($regexToRoutesMap);
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$suffixLen++;
|
||||
$suffix .= "\t";
|
||||
|
||||
$regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})';
|
||||
$routeMap[$suffix] = [$route->handler, $route->variables];
|
||||
}
|
||||
|
||||
$regex = '~^(?|' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
28
system/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php
vendored
Normal file
28
system/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap) {
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
$numGroups = 0;
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$numVariables = count($route->variables);
|
||||
$numGroups = max($numGroups, $numVariables);
|
||||
|
||||
$regexes[] = $regex . str_repeat('()', $numGroups - $numVariables);
|
||||
$routeMap[$numGroups + 1] = [$route->handler, $route->variables];
|
||||
|
||||
++$numGroups;
|
||||
}
|
||||
|
||||
$regex = '~^(?|' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
||||
|
25
system/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php
vendored
Normal file
25
system/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap) {
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
$offset = 1;
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$regexes[] = $regex;
|
||||
$routeMap[$offset] = [$route->handler, $route->variables];
|
||||
|
||||
$offset += count($route->variables);
|
||||
}
|
||||
|
||||
$regex = '~^(?:' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
||||
|
25
system/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php
vendored
Normal file
25
system/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
class MarkBased extends RegexBasedAbstract {
|
||||
protected function getApproxChunkSize() {
|
||||
return 30;
|
||||
}
|
||||
|
||||
protected function processChunk($regexToRoutesMap) {
|
||||
$routeMap = [];
|
||||
$regexes = [];
|
||||
$markName = 'a';
|
||||
foreach ($regexToRoutesMap as $regex => $route) {
|
||||
$regexes[] = $regex . '(*MARK:' . $markName . ')';
|
||||
$routeMap[$markName] = [$route->handler, $route->variables];
|
||||
|
||||
++$markName;
|
||||
}
|
||||
|
||||
$regex = '~^(?|' . implode('|', $regexes) . ')$~';
|
||||
return ['regex' => $regex, 'routeMap' => $routeMap];
|
||||
}
|
||||
}
|
||||
|
144
system/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php
vendored
Normal file
144
system/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\DataGenerator;
|
||||
|
||||
use FastRoute\DataGenerator;
|
||||
use FastRoute\BadRouteException;
|
||||
use FastRoute\Route;
|
||||
|
||||
abstract class RegexBasedAbstract implements DataGenerator {
|
||||
protected $staticRoutes = [];
|
||||
protected $methodToRegexToRoutesMap = [];
|
||||
|
||||
protected abstract function getApproxChunkSize();
|
||||
protected abstract function processChunk($regexToRoutesMap);
|
||||
|
||||
public function addRoute($httpMethod, $routeData, $handler) {
|
||||
if ($this->isStaticRoute($routeData)) {
|
||||
$this->addStaticRoute($httpMethod, $routeData, $handler);
|
||||
} else {
|
||||
$this->addVariableRoute($httpMethod, $routeData, $handler);
|
||||
}
|
||||
}
|
||||
|
||||
public function getData() {
|
||||
if (empty($this->methodToRegexToRoutesMap)) {
|
||||
return [$this->staticRoutes, []];
|
||||
}
|
||||
|
||||
return [$this->staticRoutes, $this->generateVariableRouteData()];
|
||||
}
|
||||
|
||||
private function generateVariableRouteData() {
|
||||
$data = [];
|
||||
foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) {
|
||||
$chunkSize = $this->computeChunkSize(count($regexToRoutesMap));
|
||||
$chunks = array_chunk($regexToRoutesMap, $chunkSize, true);
|
||||
$data[$method] = array_map([$this, 'processChunk'], $chunks);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function computeChunkSize($count) {
|
||||
$numParts = max(1, round($count / $this->getApproxChunkSize()));
|
||||
return ceil($count / $numParts);
|
||||
}
|
||||
|
||||
private function isStaticRoute($routeData) {
|
||||
return count($routeData) === 1 && is_string($routeData[0]);
|
||||
}
|
||||
|
||||
private function addStaticRoute($httpMethod, $routeData, $handler) {
|
||||
$routeStr = $routeData[0];
|
||||
|
||||
if (isset($this->staticRoutes[$httpMethod][$routeStr])) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Cannot register two routes matching "%s" for method "%s"',
|
||||
$routeStr, $httpMethod
|
||||
));
|
||||
}
|
||||
|
||||
if (isset($this->methodToRegexToRoutesMap[$httpMethod])) {
|
||||
foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) {
|
||||
if ($route->matches($routeStr)) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"',
|
||||
$routeStr, $route->regex, $httpMethod
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->staticRoutes[$httpMethod][$routeStr] = $handler;
|
||||
}
|
||||
|
||||
private function addVariableRoute($httpMethod, $routeData, $handler) {
|
||||
list($regex, $variables) = $this->buildRegexForRoute($routeData);
|
||||
|
||||
if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Cannot register two routes matching "%s" for method "%s"',
|
||||
$regex, $httpMethod
|
||||
));
|
||||
}
|
||||
|
||||
$this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route(
|
||||
$httpMethod, $handler, $regex, $variables
|
||||
);
|
||||
}
|
||||
|
||||
private function buildRegexForRoute($routeData) {
|
||||
$regex = '';
|
||||
$variables = [];
|
||||
foreach ($routeData as $part) {
|
||||
if (is_string($part)) {
|
||||
$regex .= preg_quote($part, '~');
|
||||
continue;
|
||||
}
|
||||
|
||||
list($varName, $regexPart) = $part;
|
||||
|
||||
if (isset($variables[$varName])) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Cannot use the same placeholder "%s" twice', $varName
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->regexHasCapturingGroups($regexPart)) {
|
||||
throw new BadRouteException(sprintf(
|
||||
'Regex "%s" for parameter "%s" contains a capturing group',
|
||||
$regexPart, $varName
|
||||
));
|
||||
}
|
||||
|
||||
$variables[$varName] = $varName;
|
||||
$regex .= '(' . $regexPart . ')';
|
||||
}
|
||||
|
||||
return [$regex, $variables];
|
||||
}
|
||||
|
||||
private function regexHasCapturingGroups($regex) {
|
||||
if (false === strpos($regex, '(')) {
|
||||
// Needs to have at least a ( to contain a capturing group
|
||||
return false;
|
||||
}
|
||||
|
||||
// Semi-accurate detection for capturing groups
|
||||
return preg_match(
|
||||
'~
|
||||
(?:
|
||||
\(\?\(
|
||||
| \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \]
|
||||
| \\\\ .
|
||||
) (*SKIP)(*FAIL) |
|
||||
\(
|
||||
(?!
|
||||
\? (?! <(?![!=]) | P< | \' )
|
||||
| \*
|
||||
)
|
||||
~x',
|
||||
$regex
|
||||
);
|
||||
}
|
||||
}
|
25
system/vendor/nikic/fast-route/src/Dispatcher.php
vendored
Normal file
25
system/vendor/nikic/fast-route/src/Dispatcher.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface Dispatcher {
|
||||
const NOT_FOUND = 0;
|
||||
const FOUND = 1;
|
||||
const METHOD_NOT_ALLOWED = 2;
|
||||
|
||||
/**
|
||||
* Dispatches against the provided HTTP method verb and URI.
|
||||
*
|
||||
* Returns array with one of the following formats:
|
||||
*
|
||||
* [self::NOT_FOUND]
|
||||
* [self::METHOD_NOT_ALLOWED, ['GET', 'OTHER_ALLOWED_METHODS']]
|
||||
* [self::FOUND, $handler, ['varName' => 'value', ...]]
|
||||
*
|
||||
* @param string $httpMethod
|
||||
* @param string $uri
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dispatch($httpMethod, $uri);
|
||||
}
|
28
system/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php
vendored
Normal file
28
system/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class CharCountBased extends RegexBasedAbstract {
|
||||
public function __construct($data) {
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri) {
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][end($matches)];
|
||||
|
||||
$vars = [];
|
||||
$i = 0;
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[++$i];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
28
system/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php
vendored
Normal file
28
system/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupCountBased extends RegexBasedAbstract {
|
||||
public function __construct($data) {
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri) {
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][count($matches)];
|
||||
|
||||
$vars = [];
|
||||
$i = 0;
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[++$i];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
30
system/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php
vendored
Normal file
30
system/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupPosBased extends RegexBasedAbstract {
|
||||
public function __construct($data) {
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri) {
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// find first non-empty match
|
||||
for ($i = 1; '' === $matches[$i]; ++$i);
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][$i];
|
||||
|
||||
$vars = [];
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[$i++];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
28
system/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php
vendored
Normal file
28
system/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class MarkBased extends RegexBasedAbstract {
|
||||
public function __construct($data) {
|
||||
list($this->staticRouteMap, $this->variableRouteData) = $data;
|
||||
}
|
||||
|
||||
protected function dispatchVariableRoute($routeData, $uri) {
|
||||
foreach ($routeData as $data) {
|
||||
if (!preg_match($data['regex'], $uri, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($handler, $varNames) = $data['routeMap'][$matches['MARK']];
|
||||
|
||||
$vars = [];
|
||||
$i = 0;
|
||||
foreach ($varNames as $varName) {
|
||||
$vars[$varName] = $matches[++$i];
|
||||
}
|
||||
return [self::FOUND, $handler, $vars];
|
||||
}
|
||||
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
80
system/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php
vendored
Normal file
80
system/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
use FastRoute\Dispatcher;
|
||||
|
||||
abstract class RegexBasedAbstract implements Dispatcher {
|
||||
protected $staticRouteMap;
|
||||
protected $variableRouteData;
|
||||
|
||||
protected abstract function dispatchVariableRoute($routeData, $uri);
|
||||
|
||||
public function dispatch($httpMethod, $uri) {
|
||||
if (isset($this->staticRouteMap[$httpMethod][$uri])) {
|
||||
$handler = $this->staticRouteMap[$httpMethod][$uri];
|
||||
return [self::FOUND, $handler, []];
|
||||
}
|
||||
|
||||
$varRouteData = $this->variableRouteData;
|
||||
if (isset($varRouteData[$httpMethod])) {
|
||||
$result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// For HEAD requests, attempt fallback to GET
|
||||
if ($httpMethod === 'HEAD') {
|
||||
if (isset($this->staticRouteMap['GET'][$uri])) {
|
||||
$handler = $this->staticRouteMap['GET'][$uri];
|
||||
return [self::FOUND, $handler, []];
|
||||
}
|
||||
if (isset($varRouteData['GET'])) {
|
||||
$result = $this->dispatchVariableRoute($varRouteData['GET'], $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing else matches, try fallback routes
|
||||
if (isset($this->staticRouteMap['*'][$uri])) {
|
||||
$handler = $this->staticRouteMap['*'][$uri];
|
||||
return [self::FOUND, $handler, []];
|
||||
}
|
||||
if (isset($varRouteData['*'])) {
|
||||
$result = $this->dispatchVariableRoute($varRouteData['*'], $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Find allowed methods for this URI by matching against all other HTTP methods as well
|
||||
$allowedMethods = [];
|
||||
|
||||
foreach ($this->staticRouteMap as $method => $uriMap) {
|
||||
if ($method !== $httpMethod && isset($uriMap[$uri])) {
|
||||
$allowedMethods[] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($varRouteData as $method => $routeData) {
|
||||
if ($method === $httpMethod) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->dispatchVariableRoute($routeData, $uri);
|
||||
if ($result[0] === self::FOUND) {
|
||||
$allowedMethods[] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no allowed methods the route simply does not exist
|
||||
if ($allowedMethods) {
|
||||
return [self::METHOD_NOT_ALLOWED, $allowedMethods];
|
||||
} else {
|
||||
return [self::NOT_FOUND];
|
||||
}
|
||||
}
|
||||
}
|
38
system/vendor/nikic/fast-route/src/Route.php
vendored
Normal file
38
system/vendor/nikic/fast-route/src/Route.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class Route {
|
||||
public $httpMethod;
|
||||
public $regex;
|
||||
public $variables;
|
||||
public $handler;
|
||||
|
||||
/**
|
||||
* Constructs a route (value object).
|
||||
*
|
||||
* @param string $httpMethod
|
||||
* @param mixed $handler
|
||||
* @param string $regex
|
||||
* @param array $variables
|
||||
*/
|
||||
public function __construct($httpMethod, $handler, $regex, $variables) {
|
||||
$this->httpMethod = $httpMethod;
|
||||
$this->handler = $handler;
|
||||
$this->regex = $regex;
|
||||
$this->variables = $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this route matches the given string.
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matches($str) {
|
||||
$regex = '~^' . $this->regex . '$~';
|
||||
return (bool) preg_match($regex, $str);
|
||||
}
|
||||
}
|
||||
|
136
system/vendor/nikic/fast-route/src/RouteCollector.php
vendored
Normal file
136
system/vendor/nikic/fast-route/src/RouteCollector.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class RouteCollector {
|
||||
protected $routeParser;
|
||||
protected $dataGenerator;
|
||||
protected $currentGroupPrefix;
|
||||
|
||||
/**
|
||||
* Constructs a route collector.
|
||||
*
|
||||
* @param RouteParser $routeParser
|
||||
* @param DataGenerator $dataGenerator
|
||||
*/
|
||||
public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator) {
|
||||
$this->routeParser = $routeParser;
|
||||
$this->dataGenerator = $dataGenerator;
|
||||
$this->currentGroupPrefix = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route to the collection.
|
||||
*
|
||||
* The syntax used in the $route string depends on the used route parser.
|
||||
*
|
||||
* @param string|string[] $httpMethod
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function addRoute($httpMethod, $route, $handler) {
|
||||
$route = $this->currentGroupPrefix . $route;
|
||||
$routeDatas = $this->routeParser->parse($route);
|
||||
foreach ((array) $httpMethod as $method) {
|
||||
foreach ($routeDatas as $routeData) {
|
||||
$this->dataGenerator->addRoute($method, $routeData, $handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a route group with a common prefix.
|
||||
*
|
||||
* All routes created in the passed callback will have the given group prefix prepended.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function addGroup($prefix, callable $callback) {
|
||||
$previousGroupPrefix = $this->currentGroupPrefix;
|
||||
$this->currentGroupPrefix = $previousGroupPrefix . $prefix;
|
||||
$callback($this);
|
||||
$this->currentGroupPrefix = $previousGroupPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a GET route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('GET', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function get($route, $handler) {
|
||||
$this->addRoute('GET', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a POST route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('POST', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function post($route, $handler) {
|
||||
$this->addRoute('POST', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PUT route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('PUT', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function put($route, $handler) {
|
||||
$this->addRoute('PUT', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DELETE route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('DELETE', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function delete($route, $handler) {
|
||||
$this->addRoute('DELETE', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PATCH route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('PATCH', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function patch($route, $handler) {
|
||||
$this->addRoute('PATCH', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a HEAD route to the collection
|
||||
*
|
||||
* This is simply an alias of $this->addRoute('HEAD', $route, $handler)
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $handler
|
||||
*/
|
||||
public function head($route, $handler) {
|
||||
$this->addRoute('HEAD', $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collected route data, as provided by the data generator.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData() {
|
||||
return $this->dataGenerator->getData();
|
||||
}
|
||||
}
|
36
system/vendor/nikic/fast-route/src/RouteParser.php
vendored
Normal file
36
system/vendor/nikic/fast-route/src/RouteParser.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
interface RouteParser {
|
||||
/**
|
||||
* Parses a route string into multiple route data arrays.
|
||||
*
|
||||
* The expected output is defined using an example:
|
||||
*
|
||||
* For the route string "/fixedRoutePart/{varName}[/moreFixed/{varName2:\d+}]", if {varName} is interpreted as
|
||||
* a placeholder and [...] is interpreted as an optional route part, the expected result is:
|
||||
*
|
||||
* [
|
||||
* // first route: without optional part
|
||||
* [
|
||||
* "/fixedRoutePart/",
|
||||
* ["varName", "[^/]+"],
|
||||
* ],
|
||||
* // second route: with optional part
|
||||
* [
|
||||
* "/fixedRoutePart/",
|
||||
* ["varName", "[^/]+"],
|
||||
* "/moreFixed/",
|
||||
* ["varName2", [0-9]+"],
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* Here one route string was converted into two route data arrays.
|
||||
*
|
||||
* @param string $route Route string to parse
|
||||
*
|
||||
* @return mixed[][] Array of route data arrays
|
||||
*/
|
||||
public function parse($route);
|
||||
}
|
81
system/vendor/nikic/fast-route/src/RouteParser/Std.php
vendored
Normal file
81
system/vendor/nikic/fast-route/src/RouteParser/Std.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\RouteParser;
|
||||
|
||||
use FastRoute\BadRouteException;
|
||||
use FastRoute\RouteParser;
|
||||
|
||||
/**
|
||||
* Parses route strings of the following form:
|
||||
*
|
||||
* "/user/{name}[/{id:[0-9]+}]"
|
||||
*/
|
||||
class Std implements RouteParser {
|
||||
const VARIABLE_REGEX = <<<'REGEX'
|
||||
\{
|
||||
\s* ([a-zA-Z_][a-zA-Z0-9_-]*) \s*
|
||||
(?:
|
||||
: \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
|
||||
)?
|
||||
\}
|
||||
REGEX;
|
||||
const DEFAULT_DISPATCH_REGEX = '[^/]+';
|
||||
|
||||
public function parse($route) {
|
||||
$routeWithoutClosingOptionals = rtrim($route, ']');
|
||||
$numOptionals = strlen($route) - strlen($routeWithoutClosingOptionals);
|
||||
|
||||
// Split on [ while skipping placeholders
|
||||
$segments = preg_split('~' . self::VARIABLE_REGEX . '(*SKIP)(*F) | \[~x', $routeWithoutClosingOptionals);
|
||||
if ($numOptionals !== count($segments) - 1) {
|
||||
// If there are any ] in the middle of the route, throw a more specific error message
|
||||
if (preg_match('~' . self::VARIABLE_REGEX . '(*SKIP)(*F) | \]~x', $routeWithoutClosingOptionals)) {
|
||||
throw new BadRouteException("Optional segments can only occur at the end of a route");
|
||||
}
|
||||
throw new BadRouteException("Number of opening '[' and closing ']' does not match");
|
||||
}
|
||||
|
||||
$currentRoute = '';
|
||||
$routeDatas = [];
|
||||
foreach ($segments as $n => $segment) {
|
||||
if ($segment === '' && $n !== 0) {
|
||||
throw new BadRouteException("Empty optional part");
|
||||
}
|
||||
|
||||
$currentRoute .= $segment;
|
||||
$routeDatas[] = $this->parsePlaceholders($currentRoute);
|
||||
}
|
||||
return $routeDatas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a route string that does not contain optional segments.
|
||||
*/
|
||||
private function parsePlaceholders($route) {
|
||||
if (!preg_match_all(
|
||||
'~' . self::VARIABLE_REGEX . '~x', $route, $matches,
|
||||
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
|
||||
)) {
|
||||
return [$route];
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
$routeData = [];
|
||||
foreach ($matches as $set) {
|
||||
if ($set[0][1] > $offset) {
|
||||
$routeData[] = substr($route, $offset, $set[0][1] - $offset);
|
||||
}
|
||||
$routeData[] = [
|
||||
$set[1][0],
|
||||
isset($set[2]) ? trim($set[2][0]) : self::DEFAULT_DISPATCH_REGEX
|
||||
];
|
||||
$offset = $set[0][1] + strlen($set[0][0]);
|
||||
}
|
||||
|
||||
if ($offset != strlen($route)) {
|
||||
$routeData[] = substr($route, $offset);
|
||||
}
|
||||
|
||||
return $routeData;
|
||||
}
|
||||
}
|
12
system/vendor/nikic/fast-route/src/bootstrap.php
vendored
Normal file
12
system/vendor/nikic/fast-route/src/bootstrap.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
require __DIR__ . '/functions.php';
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
if (strpos($class, 'FastRoute\\') === 0) {
|
||||
$name = substr($class, strlen('FastRoute'));
|
||||
require __DIR__ . strtr($name, '\\', DIRECTORY_SEPARATOR) . '.php';
|
||||
}
|
||||
});
|
72
system/vendor/nikic/fast-route/src/functions.php
vendored
Normal file
72
system/vendor/nikic/fast-route/src/functions.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
if (!function_exists('FastRoute\simpleDispatcher')) {
|
||||
/**
|
||||
* @param callable $routeDefinitionCallback
|
||||
* @param array $options
|
||||
*
|
||||
* @return Dispatcher
|
||||
*/
|
||||
function simpleDispatcher(callable $routeDefinitionCallback, array $options = []) {
|
||||
$options += [
|
||||
'routeParser' => 'FastRoute\\RouteParser\\Std',
|
||||
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
|
||||
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
|
||||
'routeCollector' => 'FastRoute\\RouteCollector',
|
||||
];
|
||||
|
||||
/** @var RouteCollector $routeCollector */
|
||||
$routeCollector = new $options['routeCollector'](
|
||||
new $options['routeParser'], new $options['dataGenerator']
|
||||
);
|
||||
$routeDefinitionCallback($routeCollector);
|
||||
|
||||
return new $options['dispatcher']($routeCollector->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $routeDefinitionCallback
|
||||
* @param array $options
|
||||
*
|
||||
* @return Dispatcher
|
||||
*/
|
||||
function cachedDispatcher(callable $routeDefinitionCallback, array $options = []) {
|
||||
$options += [
|
||||
'routeParser' => 'FastRoute\\RouteParser\\Std',
|
||||
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
|
||||
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
|
||||
'routeCollector' => 'FastRoute\\RouteCollector',
|
||||
'cacheDisabled' => false,
|
||||
];
|
||||
|
||||
if (!isset($options['cacheFile'])) {
|
||||
throw new \LogicException('Must specify "cacheFile" option');
|
||||
}
|
||||
|
||||
if (!$options['cacheDisabled'] && file_exists($options['cacheFile'])) {
|
||||
$dispatchData = require $options['cacheFile'];
|
||||
if (!is_array($dispatchData)) {
|
||||
throw new \RuntimeException('Invalid cache file "' . $options['cacheFile'] . '"');
|
||||
}
|
||||
return new $options['dispatcher']($dispatchData);
|
||||
}
|
||||
|
||||
$routeCollector = new $options['routeCollector'](
|
||||
new $options['routeParser'], new $options['dataGenerator']
|
||||
);
|
||||
$routeDefinitionCallback($routeCollector);
|
||||
|
||||
/** @var RouteCollector $routeCollector */
|
||||
$dispatchData = $routeCollector->getData();
|
||||
if (!$options['cacheDisabled']) {
|
||||
file_put_contents(
|
||||
$options['cacheFile'],
|
||||
'<?php return ' . var_export($dispatchData, true) . ';'
|
||||
);
|
||||
}
|
||||
|
||||
return new $options['dispatcher']($dispatchData);
|
||||
}
|
||||
}
|
13
system/vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php
vendored
Normal file
13
system/vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class CharCountBasedTest extends DispatcherTest {
|
||||
protected function getDispatcherClass() {
|
||||
return 'FastRoute\\Dispatcher\\CharCountBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass() {
|
||||
return 'FastRoute\\DataGenerator\\CharCountBased';
|
||||
}
|
||||
}
|
561
system/vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php
vendored
Normal file
561
system/vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php
vendored
Normal file
@@ -0,0 +1,561 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
use FastRoute\RouteCollector;
|
||||
|
||||
abstract class DispatcherTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* Delegate dispatcher selection to child test classes
|
||||
*/
|
||||
abstract protected function getDispatcherClass();
|
||||
|
||||
/**
|
||||
* Delegate dataGenerator selection to child test classes
|
||||
*/
|
||||
abstract protected function getDataGeneratorClass();
|
||||
|
||||
/**
|
||||
* Set appropriate options for the specific Dispatcher class we're testing
|
||||
*/
|
||||
private function generateDispatcherOptions() {
|
||||
return [
|
||||
'dataGenerator' => $this->getDataGeneratorClass(),
|
||||
'dispatcher' => $this->getDispatcherClass()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideFoundDispatchCases
|
||||
*/
|
||||
public function testFoundDispatches($method, $uri, $callback, $handler, $argDict) {
|
||||
$dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions());
|
||||
$info = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertSame($dispatcher::FOUND, $info[0]);
|
||||
$this->assertSame($handler, $info[1]);
|
||||
$this->assertSame($argDict, $info[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideNotFoundDispatchCases
|
||||
*/
|
||||
public function testNotFoundDispatches($method, $uri, $callback) {
|
||||
$dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions());
|
||||
$routeInfo = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertFalse(isset($routeInfo[1]),
|
||||
"NOT_FOUND result must only contain a single element in the returned info array"
|
||||
);
|
||||
$this->assertSame($dispatcher::NOT_FOUND, $routeInfo[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMethodNotAllowedDispatchCases
|
||||
*/
|
||||
public function testMethodNotAllowedDispatches($method, $uri, $callback, $availableMethods) {
|
||||
$dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions());
|
||||
$routeInfo = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertTrue(isset($routeInfo[1]),
|
||||
"METHOD_NOT_ALLOWED result must return an array of allowed methods at index 1"
|
||||
);
|
||||
|
||||
list($routedStatus, $methodArray) = $dispatcher->dispatch($method, $uri);
|
||||
$this->assertSame($dispatcher::METHOD_NOT_ALLOWED, $routedStatus);
|
||||
$this->assertSame($availableMethods, $methodArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Cannot use the same placeholder "test" twice
|
||||
*/
|
||||
public function testDuplicateVariableNameError() {
|
||||
\FastRoute\simpleDispatcher(function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/foo/{test}/{test:\d+}', 'handler0');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Cannot register two routes matching "/user/([^/]+)" for method "GET"
|
||||
*/
|
||||
public function testDuplicateVariableRoute() {
|
||||
\FastRoute\simpleDispatcher(function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{id}', 'handler0'); // oops, forgot \d+ restriction ;)
|
||||
$r->addRoute('GET', '/user/{name}', 'handler1');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Cannot register two routes matching "/user" for method "GET"
|
||||
*/
|
||||
public function testDuplicateStaticRoute() {
|
||||
\FastRoute\simpleDispatcher(function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user', 'handler0');
|
||||
$r->addRoute('GET', '/user', 'handler1');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Static route "/user/nikic" is shadowed by previously defined variable route "/user/([^/]+)" for method "GET"
|
||||
*/
|
||||
public function testShadowedStaticRoute() {
|
||||
\FastRoute\simpleDispatcher(function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('GET', '/user/nikic', 'handler1');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \FastRoute\BadRouteException
|
||||
* @expectedExceptionMessage Regex "(en|de)" for parameter "lang" contains a capturing group
|
||||
*/
|
||||
public function testCapturing() {
|
||||
\FastRoute\simpleDispatcher(function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/{lang:(en|de)}', 'handler0');
|
||||
}, $this->generateDispatcherOptions());
|
||||
}
|
||||
|
||||
public function provideFoundDispatchCases() {
|
||||
$cases = [];
|
||||
|
||||
// 0 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/resource/123/456';
|
||||
$handler = 'handler0';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 1 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/handler0', 'handler0');
|
||||
$r->addRoute('GET', '/handler1', 'handler1');
|
||||
$r->addRoute('GET', '/handler2', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/handler2';
|
||||
$handler = 'handler2';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 2 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/user/{name}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler2';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 3 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse $callback from #2
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/12345';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['id' => '12345'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 4 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse $callback from #3
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/NaN';
|
||||
$handler = 'handler2';
|
||||
$argDict = ['name' => 'NaN'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 5 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse $callback from #4
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey/12345';
|
||||
$handler = 'handler0';
|
||||
$argDict = ['name' => 'rdlowrey', 'id' => '12345'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 6 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/12345/extension', 'handler1');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', 'handler2');
|
||||
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/12345.svg';
|
||||
$handler = 'handler2';
|
||||
$argDict = ['id' => '12345', 'extension' => 'svg'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 7 ----- Test GET method fallback on HEAD route miss ------------------------------------>
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/static0', 'handler2');
|
||||
$r->addRoute('GET', '/static1', 'handler3');
|
||||
$r->addRoute('HEAD', '/static1', 'handler4');
|
||||
};
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler0';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 8 ----- Test GET method fallback on HEAD route miss ------------------------------------>
|
||||
|
||||
// reuse $callback from #7
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/user/rdlowrey/1234';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey', 'id' => '1234'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 9 ----- Test GET method fallback on HEAD route miss ------------------------------------>
|
||||
|
||||
// reuse $callback from #8
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/static0';
|
||||
$handler = 'handler2';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 10 ---- Test existing HEAD route used if available (no fallback) ----------------------->
|
||||
|
||||
// reuse $callback from #9
|
||||
|
||||
$method = 'HEAD';
|
||||
$uri = '/static1';
|
||||
$handler = 'handler4';
|
||||
$argDict = [];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 11 ---- More specified routes are not shadowed by less specific of another method ------>
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1');
|
||||
};
|
||||
|
||||
$method = 'POST';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 12 ---- Handler of more specific routes is used, if it occurs first -------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1');
|
||||
$r->addRoute('POST', '/user/{name}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'POST';
|
||||
$uri = '/user/rdlowrey';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 13 ---- Route with constant suffix ----------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{name}/edit', 'handler1');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey/edit';
|
||||
$handler = 'handler1';
|
||||
$argDict = ['name' => 'rdlowrey'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $handler, $argDict];
|
||||
|
||||
// 14 ---- Handle multiple methods with the same handler ---------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost');
|
||||
$r->addRoute(['DELETE'], '/user', 'handlerDelete');
|
||||
$r->addRoute([], '/user', 'handlerNone');
|
||||
};
|
||||
|
||||
$argDict = [];
|
||||
$cases[] = ['GET', '/user', $callback, 'handlerGetPost', $argDict];
|
||||
$cases[] = ['POST', '/user', $callback, 'handlerGetPost', $argDict];
|
||||
$cases[] = ['DELETE', '/user', $callback, 'handlerDelete', $argDict];
|
||||
|
||||
// 15 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('POST', '/user.json', 'handler0');
|
||||
$r->addRoute('GET', '/{entity}.json', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '/user.json', $callback, 'handler1', ['entity' => 'user']];
|
||||
|
||||
// 16 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '', 'handler0');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '', $callback, 'handler0', []];
|
||||
|
||||
// 17 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('HEAD', '/a/{foo}', 'handler0');
|
||||
$r->addRoute('GET', '/b/{foo}', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['HEAD', '/b/bar', $callback, 'handler1', ['foo' => 'bar']];
|
||||
|
||||
// 18 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('HEAD', '/a', 'handler0');
|
||||
$r->addRoute('GET', '/b', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['HEAD', '/b', $callback, 'handler1', []];
|
||||
|
||||
// 19 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/foo', 'handler0');
|
||||
$r->addRoute('HEAD', '/{bar}', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['HEAD', '/foo', $callback, 'handler1', ['bar' => 'foo']];
|
||||
|
||||
// 20 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('*', '/user', 'handler0');
|
||||
$r->addRoute('*', '/{user}', 'handler1');
|
||||
$r->addRoute('GET', '/user', 'handler2');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '/user', $callback, 'handler2', []];
|
||||
|
||||
// 21 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('*', '/user', 'handler0');
|
||||
$r->addRoute('GET', '/user', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['POST', '/user', $callback, 'handler0', []];
|
||||
|
||||
// 22 ----
|
||||
|
||||
$cases[] = ['HEAD', '/user', $callback, 'handler1', []];
|
||||
|
||||
// 23 ----
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/{bar}', 'handler0');
|
||||
$r->addRoute('*', '/foo', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['GET', '/foo', $callback, 'handler0', ['bar' => 'foo']];
|
||||
|
||||
// x -------------------------------------------------------------------------------------->
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
public function provideNotFoundDispatchCases() {
|
||||
$cases = [];
|
||||
|
||||
// 0 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 1 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #0
|
||||
$method = 'POST';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 2 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #1
|
||||
$method = 'PUT';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 3 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/handler0', 'handler0');
|
||||
$r->addRoute('GET', '/handler1', 'handler1');
|
||||
$r->addRoute('GET', '/handler2', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 4 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('GET', '/user/{name}', 'handler2');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 5 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #4
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey/12345/not-found';
|
||||
|
||||
$cases[] = [$method, $uri, $callback];
|
||||
|
||||
// 6 -------------------------------------------------------------------------------------->
|
||||
|
||||
// reuse callback from #5
|
||||
$method = 'HEAD';
|
||||
|
||||
$cases[] = array($method, $uri, $callback);
|
||||
|
||||
// x -------------------------------------------------------------------------------------->
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
public function provideMethodNotAllowedDispatchCases() {
|
||||
$cases = [];
|
||||
|
||||
// 0 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
};
|
||||
|
||||
$method = 'POST';
|
||||
$uri = '/resource/123/456';
|
||||
$allowedMethods = ['GET'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 1 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/resource/123/456', 'handler0');
|
||||
$r->addRoute('POST', '/resource/123/456', 'handler1');
|
||||
$r->addRoute('PUT', '/resource/123/456', 'handler2');
|
||||
$r->addRoute('*', '/', 'handler3');
|
||||
};
|
||||
|
||||
$method = 'DELETE';
|
||||
$uri = '/resource/123/456';
|
||||
$allowedMethods = ['GET', 'POST', 'PUT'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 2 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
|
||||
$r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1');
|
||||
$r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2');
|
||||
$r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3');
|
||||
};
|
||||
|
||||
$method = 'DELETE';
|
||||
$uri = '/user/rdlowrey/42';
|
||||
$allowedMethods = ['GET', 'POST', 'PUT', 'PATCH'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 3 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('POST', '/user/{name}', 'handler1');
|
||||
$r->addRoute('PUT', '/user/{name:[a-z]+}', 'handler2');
|
||||
$r->addRoute('PATCH', '/user/{name:[a-z]+}', 'handler3');
|
||||
};
|
||||
|
||||
$method = 'GET';
|
||||
$uri = '/user/rdlowrey';
|
||||
$allowedMethods = ['POST', 'PUT', 'PATCH'];
|
||||
|
||||
$cases[] = [$method, $uri, $callback, $allowedMethods];
|
||||
|
||||
// 4 -------------------------------------------------------------------------------------->
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost');
|
||||
$r->addRoute(['DELETE'], '/user', 'handlerDelete');
|
||||
$r->addRoute([], '/user', 'handlerNone');
|
||||
};
|
||||
|
||||
$cases[] = ['PUT', '/user', $callback, ['GET', 'POST', 'DELETE']];
|
||||
|
||||
// 5
|
||||
|
||||
$callback = function(RouteCollector $r) {
|
||||
$r->addRoute('POST', '/user.json', 'handler0');
|
||||
$r->addRoute('GET', '/{entity}.json', 'handler1');
|
||||
};
|
||||
|
||||
$cases[] = ['PUT', '/user.json', $callback, ['POST', 'GET']];
|
||||
|
||||
// x -------------------------------------------------------------------------------------->
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
}
|
13
system/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php
vendored
Normal file
13
system/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupCountBasedTest extends DispatcherTest {
|
||||
protected function getDispatcherClass() {
|
||||
return 'FastRoute\\Dispatcher\\GroupCountBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass() {
|
||||
return 'FastRoute\\DataGenerator\\GroupCountBased';
|
||||
}
|
||||
}
|
13
system/vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php
vendored
Normal file
13
system/vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class GroupPosBasedTest extends DispatcherTest {
|
||||
protected function getDispatcherClass() {
|
||||
return 'FastRoute\\Dispatcher\\GroupPosBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass() {
|
||||
return 'FastRoute\\DataGenerator\\GroupPosBased';
|
||||
}
|
||||
}
|
20
system/vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php
vendored
Normal file
20
system/vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\Dispatcher;
|
||||
|
||||
class MarkBasedTest extends DispatcherTest {
|
||||
public function setUp() {
|
||||
preg_match('/(*MARK:A)a/', 'a', $matches);
|
||||
if (!isset($matches['MARK'])) {
|
||||
$this->markTestSkipped('PHP 5.6 required for MARK support');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getDispatcherClass() {
|
||||
return 'FastRoute\\Dispatcher\\MarkBased';
|
||||
}
|
||||
|
||||
protected function getDataGeneratorClass() {
|
||||
return 'FastRoute\\DataGenerator\\MarkBased';
|
||||
}
|
||||
}
|
39
system/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php
vendored
Normal file
39
system/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class HackTypecheckerTest extends \PhpUnit_Framework_TestCase {
|
||||
const SERVER_ALREADY_RUNNING_CODE = 77;
|
||||
public function testTypechecks($recurse = true) {
|
||||
if (!defined('HHVM_VERSION')) {
|
||||
$this->markTestSkipped("HHVM only");
|
||||
}
|
||||
if (!version_compare(HHVM_VERSION, '3.9.0', '>=')) {
|
||||
$this->markTestSkipped('classname<T> requires HHVM 3.9+');
|
||||
}
|
||||
|
||||
// The typechecker recurses the whole tree, so it makes sure
|
||||
// that everything in fixtures/ is valid when this runs.
|
||||
|
||||
$output = array();
|
||||
$exit_code = null;
|
||||
exec(
|
||||
'hh_server --check '.escapeshellarg(__DIR__.'/../../').' 2>&1',
|
||||
$output,
|
||||
$exit_code
|
||||
);
|
||||
if ($exit_code === self::SERVER_ALREADY_RUNNING_CODE) {
|
||||
$this->assertTrue(
|
||||
$recurse,
|
||||
"Typechecker still running after running hh_client stop"
|
||||
);
|
||||
// Server already running - 3.10 => 3.11 regression:
|
||||
// https://github.com/facebook/hhvm/issues/6646
|
||||
exec('hh_client stop 2>/dev/null');
|
||||
$this->testTypechecks(/* recurse = */ false);
|
||||
return;
|
||||
|
||||
}
|
||||
$this->assertSame(0, $exit_code, implode("\n", $output));
|
||||
}
|
||||
}
|
29
system/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php
vendored
Normal file
29
system/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?hh
|
||||
|
||||
namespace FastRoute\TestFixtures;
|
||||
|
||||
function all_options_simple(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\simpleDispatcher(
|
||||
$collector ==> {},
|
||||
shape(
|
||||
'routeParser' => \FastRoute\RouteParser\Std::class,
|
||||
'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class,
|
||||
'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class,
|
||||
'routeCollector' => \FastRoute\RouteCollector::class,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function all_options_cached(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\cachedDispatcher(
|
||||
$collector ==> {},
|
||||
shape(
|
||||
'routeParser' => \FastRoute\RouteParser\Std::class,
|
||||
'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class,
|
||||
'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class,
|
||||
'routeCollector' => \FastRoute\RouteCollector::class,
|
||||
'cacheFile' => '/dev/null',
|
||||
'cacheDisabled' => false,
|
||||
),
|
||||
);
|
||||
}
|
11
system/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php
vendored
Normal file
11
system/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?hh
|
||||
|
||||
namespace FastRoute\TestFixtures;
|
||||
|
||||
function empty_options_simple(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\simpleDispatcher($collector ==> {}, shape());
|
||||
}
|
||||
|
||||
function empty_options_cached(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\cachedDispatcher($collector ==> {}, shape());
|
||||
}
|
11
system/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php
vendored
Normal file
11
system/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?hh
|
||||
|
||||
namespace FastRoute\TestFixtures;
|
||||
|
||||
function no_options_simple(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\simpleDispatcher($collector ==> {});
|
||||
}
|
||||
|
||||
function no_options_cached(): \FastRoute\Dispatcher {
|
||||
return \FastRoute\cachedDispatcher($collector ==> {});
|
||||
}
|
97
system/vendor/nikic/fast-route/test/RouteCollectorTest.php
vendored
Normal file
97
system/vendor/nikic/fast-route/test/RouteCollectorTest.php
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute;
|
||||
|
||||
class RouteCollectorTest extends \PHPUnit_Framework_TestCase {
|
||||
public function testShortcuts() {
|
||||
$r = new DummyRouteCollector();
|
||||
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
|
||||
$expected = [
|
||||
['DELETE', '/delete', 'delete'],
|
||||
['GET', '/get', 'get'],
|
||||
['HEAD', '/head', 'head'],
|
||||
['PATCH', '/patch', 'patch'],
|
||||
['POST', '/post', 'post'],
|
||||
['PUT', '/put', 'put'],
|
||||
];
|
||||
|
||||
$this->assertSame($expected, $r->routes);
|
||||
}
|
||||
|
||||
public function testGroups() {
|
||||
$r = new DummyRouteCollector();
|
||||
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
|
||||
$r->addGroup('/group-one', function (DummyRouteCollector $r) {
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
|
||||
$r->addGroup('/group-two', function (DummyRouteCollector $r) {
|
||||
$r->delete('/delete', 'delete');
|
||||
$r->get('/get', 'get');
|
||||
$r->head('/head', 'head');
|
||||
$r->patch('/patch', 'patch');
|
||||
$r->post('/post', 'post');
|
||||
$r->put('/put', 'put');
|
||||
});
|
||||
});
|
||||
|
||||
$r->addGroup('/admin', function (DummyRouteCollector $r) {
|
||||
$r->get('-some-info', 'admin-some-info');
|
||||
});
|
||||
$r->addGroup('/admin-', function (DummyRouteCollector $r) {
|
||||
$r->get('more-info', 'admin-more-info');
|
||||
});
|
||||
|
||||
$expected = [
|
||||
['DELETE', '/delete', 'delete'],
|
||||
['GET', '/get', 'get'],
|
||||
['HEAD', '/head', 'head'],
|
||||
['PATCH', '/patch', 'patch'],
|
||||
['POST', '/post', 'post'],
|
||||
['PUT', '/put', 'put'],
|
||||
['DELETE', '/group-one/delete', 'delete'],
|
||||
['GET', '/group-one/get', 'get'],
|
||||
['HEAD', '/group-one/head', 'head'],
|
||||
['PATCH', '/group-one/patch', 'patch'],
|
||||
['POST', '/group-one/post', 'post'],
|
||||
['PUT', '/group-one/put', 'put'],
|
||||
['DELETE', '/group-one/group-two/delete', 'delete'],
|
||||
['GET', '/group-one/group-two/get', 'get'],
|
||||
['HEAD', '/group-one/group-two/head', 'head'],
|
||||
['PATCH', '/group-one/group-two/patch', 'patch'],
|
||||
['POST', '/group-one/group-two/post', 'post'],
|
||||
['PUT', '/group-one/group-two/put', 'put'],
|
||||
['GET', '/admin-some-info', 'admin-some-info'],
|
||||
['GET', '/admin-more-info', 'admin-more-info'],
|
||||
];
|
||||
|
||||
$this->assertSame($expected, $r->routes);
|
||||
}
|
||||
}
|
||||
|
||||
class DummyRouteCollector extends RouteCollector {
|
||||
public $routes = [];
|
||||
public function __construct() {}
|
||||
public function addRoute($method, $route, $handler) {
|
||||
$route = $this->currentGroupPrefix . $route;
|
||||
$this->routes[] = [$method, $route, $handler];
|
||||
}
|
||||
}
|
147
system/vendor/nikic/fast-route/test/RouteParser/StdTest.php
vendored
Normal file
147
system/vendor/nikic/fast-route/test/RouteParser/StdTest.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace FastRoute\RouteParser;
|
||||
|
||||
class StdTest extends \PhpUnit_Framework_TestCase {
|
||||
/** @dataProvider provideTestParse */
|
||||
public function testParse($routeString, $expectedRouteDatas) {
|
||||
$parser = new Std();
|
||||
$routeDatas = $parser->parse($routeString);
|
||||
$this->assertSame($expectedRouteDatas, $routeDatas);
|
||||
}
|
||||
|
||||
/** @dataProvider provideTestParseError */
|
||||
public function testParseError($routeString, $expectedExceptionMessage) {
|
||||
$parser = new Std();
|
||||
$this->setExpectedException('FastRoute\\BadRouteException', $expectedExceptionMessage);
|
||||
$parser->parse($routeString);
|
||||
}
|
||||
|
||||
public function provideTestParse() {
|
||||
return [
|
||||
[
|
||||
'/test',
|
||||
[
|
||||
['/test'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{param}',
|
||||
[
|
||||
['/test/', ['param', '[^/]+']],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/te{ param }st',
|
||||
[
|
||||
['/te', ['param', '[^/]+'], 'st']
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{param1}/test2/{param2}',
|
||||
[
|
||||
['/test/', ['param1', '[^/]+'], '/test2/', ['param2', '[^/]+']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{param:\d+}',
|
||||
[
|
||||
['/test/', ['param', '\d+']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test/{ param : \d{1,9} }',
|
||||
[
|
||||
['/test/', ['param', '\d{1,9}']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test[opt]',
|
||||
[
|
||||
['/test'],
|
||||
['/testopt'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test[/{param}]',
|
||||
[
|
||||
['/test'],
|
||||
['/test/', ['param', '[^/]+']],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/{param}[opt]',
|
||||
[
|
||||
['/', ['param', '[^/]+']],
|
||||
['/', ['param', '[^/]+'], 'opt']
|
||||
]
|
||||
],
|
||||
[
|
||||
'/test[/{name}[/{id:[0-9]+}]]',
|
||||
[
|
||||
['/test'],
|
||||
['/test/', ['name', '[^/]+']],
|
||||
['/test/', ['name', '[^/]+'], '/', ['id', '[0-9]+']],
|
||||
]
|
||||
],
|
||||
[
|
||||
'',
|
||||
[
|
||||
[''],
|
||||
]
|
||||
],
|
||||
[
|
||||
'[test]',
|
||||
[
|
||||
[''],
|
||||
['test'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'/{foo-bar}',
|
||||
[
|
||||
['/', ['foo-bar', '[^/]+']]
|
||||
]
|
||||
],
|
||||
[
|
||||
'/{_foo:.*}',
|
||||
[
|
||||
['/', ['_foo', '.*']]
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function provideTestParseError() {
|
||||
return [
|
||||
[
|
||||
'/test[opt',
|
||||
"Number of opening '[' and closing ']' does not match"
|
||||
],
|
||||
[
|
||||
'/test[opt[opt2]',
|
||||
"Number of opening '[' and closing ']' does not match"
|
||||
],
|
||||
[
|
||||
'/testopt]',
|
||||
"Number of opening '[' and closing ']' does not match"
|
||||
],
|
||||
[
|
||||
'/test[]',
|
||||
"Empty optional part"
|
||||
],
|
||||
[
|
||||
'/test[[opt]]',
|
||||
"Empty optional part"
|
||||
],
|
||||
[
|
||||
'[[test]]',
|
||||
"Empty optional part"
|
||||
],
|
||||
[
|
||||
'/test[/opt]/required',
|
||||
"Optional segments can only occur at the end of a route"
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
11
system/vendor/nikic/fast-route/test/bootstrap.php
vendored
Normal file
11
system/vendor/nikic/fast-route/test/bootstrap.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../src/functions.php';
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
if (strpos($class, 'FastRoute\\') === 0) {
|
||||
$dir = strcasecmp(substr($class, -4), 'Test') ? 'src/' : 'test/';
|
||||
$name = substr($class, strlen('FastRoute'));
|
||||
require __DIR__ . '/../' . $dir . strtr($name, '\\', DIRECTORY_SEPARATOR) . '.php';
|
||||
}
|
||||
});
|
3
system/vendor/pimple/pimple/.gitignore
vendored
Normal file
3
system/vendor/pimple/pimple/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
phpunit.xml
|
||||
composer.lock
|
||||
/vendor/
|
32
system/vendor/pimple/pimple/.travis.yml
vendored
Normal file
32
system/vendor/pimple/pimple/.travis.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
language: php
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- PIMPLE_EXT=no
|
||||
- PIMPLE_EXT=yes
|
||||
global:
|
||||
- REPORT_EXIT_STATUS=1
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- composer self-update
|
||||
- COMPOSER_ROOT_VERSION=dev-master composer dump-autoload
|
||||
- if [ "$PIMPLE_EXT" == "yes" ]; then sh -c "cd ext/pimple && phpize && ./configure && make && sudo make install"; fi
|
||||
- if [ "$PIMPLE_EXT" == "yes" ]; then echo "extension=pimple.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
|
||||
|
||||
script:
|
||||
- cd ext/pimple
|
||||
- if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi
|
||||
- cd ../..
|
||||
- phpunit
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- php: hhvm
|
||||
env: PIMPLE_EXT=yes
|
35
system/vendor/pimple/pimple/CHANGELOG
vendored
Normal file
35
system/vendor/pimple/pimple/CHANGELOG
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
* 3.0.2 (2015-09-11)
|
||||
|
||||
* refactored the C extension
|
||||
* minor non-significant changes
|
||||
|
||||
* 3.0.1 (2015-07-30)
|
||||
|
||||
* simplified some code
|
||||
* fixed a segfault in the C extension
|
||||
|
||||
* 3.0.0 (2014-07-24)
|
||||
|
||||
* removed the Pimple class alias (use Pimple\Container instead)
|
||||
|
||||
* 2.1.1 (2014-07-24)
|
||||
|
||||
* fixed compiler warnings for the C extension
|
||||
* fixed code when dealing with circular references
|
||||
|
||||
* 2.1.0 (2014-06-24)
|
||||
|
||||
* moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a
|
||||
deprecated alias which will be removed in Pimple 3.0)
|
||||
* added Pimple\ServiceProviderInterface (and Pimple::register())
|
||||
|
||||
* 2.0.0 (2014-02-10)
|
||||
|
||||
* changed extend to automatically re-assign the extended service and keep it as shared or factory
|
||||
(to keep BC, extend still returns the extended service)
|
||||
* changed services to be shared by default (use factory() for factory
|
||||
services)
|
||||
|
||||
* 1.0.0
|
||||
|
||||
* initial version
|
19
system/vendor/pimple/pimple/LICENSE
vendored
Normal file
19
system/vendor/pimple/pimple/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2009-2015 Fabien Potencier
|
||||
|
||||
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.
|
201
system/vendor/pimple/pimple/README.rst
vendored
Normal file
201
system/vendor/pimple/pimple/README.rst
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Pimple
|
||||
======
|
||||
|
||||
.. caution::
|
||||
|
||||
This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read
|
||||
the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good
|
||||
way to learn more about how to create a simple Dependency Injection
|
||||
Container (recent versions of Pimple are more focused on performance).
|
||||
|
||||
Pimple is a small Dependency Injection Container for PHP.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Before using Pimple in your project, add it to your ``composer.json`` file:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./composer.phar require pimple/pimple ~3.0
|
||||
|
||||
Alternatively, Pimple is also available as a PHP C extension:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://github.com/silexphp/Pimple
|
||||
$ cd Pimple/ext/pimple
|
||||
$ phpize
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Creating a container is a matter of creating a ``Container`` instance:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Pimple\Container;
|
||||
|
||||
$container = new Container();
|
||||
|
||||
As many other dependency injection containers, Pimple manages two different
|
||||
kind of data: **services** and **parameters**.
|
||||
|
||||
Defining Services
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
A service is an object that does something as part of a larger system. Examples
|
||||
of services: a database connection, a templating engine, or a mailer. Almost
|
||||
any **global** object can be a service.
|
||||
|
||||
Services are defined by **anonymous functions** that return an instance of an
|
||||
object:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// define some services
|
||||
$container['session_storage'] = function ($c) {
|
||||
return new SessionStorage('SESSION_ID');
|
||||
};
|
||||
|
||||
$container['session'] = function ($c) {
|
||||
return new Session($c['session_storage']);
|
||||
};
|
||||
|
||||
Notice that the anonymous function has access to the current container
|
||||
instance, allowing references to other services or parameters.
|
||||
|
||||
As objects are only created when you get them, the order of the definitions
|
||||
does not matter.
|
||||
|
||||
Using the defined services is also very easy:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// get the session object
|
||||
$session = $container['session'];
|
||||
|
||||
// the above call is roughly equivalent to the following code:
|
||||
// $storage = new SessionStorage('SESSION_ID');
|
||||
// $session = new Session($storage);
|
||||
|
||||
Defining Factory Services
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, each time you get a service, Pimple returns the **same instance**
|
||||
of it. If you want a different instance to be returned for all calls, wrap your
|
||||
anonymous function with the ``factory()`` method
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$container['session'] = $container->factory(function ($c) {
|
||||
return new Session($c['session_storage']);
|
||||
});
|
||||
|
||||
Now, each call to ``$container['session']`` returns a new instance of the
|
||||
session.
|
||||
|
||||
Defining Parameters
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Defining a parameter allows to ease the configuration of your container from
|
||||
the outside and to store global values:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// define some parameters
|
||||
$container['cookie_name'] = 'SESSION_ID';
|
||||
$container['session_storage_class'] = 'SessionStorage';
|
||||
|
||||
If you change the ``session_storage`` service definition like below:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$container['session_storage'] = function ($c) {
|
||||
return new $c['session_storage_class']($c['cookie_name']);
|
||||
};
|
||||
|
||||
You can now easily change the cookie name by overriding the
|
||||
``session_storage_class`` parameter instead of redefining the service
|
||||
definition.
|
||||
|
||||
Protecting Parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Because Pimple sees anonymous functions as service definitions, you need to
|
||||
wrap anonymous functions with the ``protect()`` method to store them as
|
||||
parameters:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$container['random_func'] = $container->protect(function () {
|
||||
return rand();
|
||||
});
|
||||
|
||||
Modifying Services after Definition
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In some cases you may want to modify a service definition after it has been
|
||||
defined. You can use the ``extend()`` method to define additional code to be
|
||||
run on your service just after it is created:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$container['session_storage'] = function ($c) {
|
||||
return new $c['session_storage_class']($c['cookie_name']);
|
||||
};
|
||||
|
||||
$container->extend('session_storage', function ($storage, $c) {
|
||||
$storage->...();
|
||||
|
||||
return $storage;
|
||||
});
|
||||
|
||||
The first argument is the name of the service to extend, the second a function
|
||||
that gets access to the object instance and the container.
|
||||
|
||||
Extending a Container
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you use the same libraries over and over, you might want to reuse some
|
||||
services from one project to the next one; package your services into a
|
||||
**provider** by implementing ``Pimple\ServiceProviderInterface``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Pimple\Container;
|
||||
|
||||
class FooProvider implements Pimple\ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $pimple)
|
||||
{
|
||||
// register some services and parameters
|
||||
// on $pimple
|
||||
}
|
||||
}
|
||||
|
||||
Then, register the provider on a Container:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$pimple->register(new FooProvider());
|
||||
|
||||
Fetching the Service Creation Function
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When you access an object, Pimple automatically calls the anonymous function
|
||||
that you defined, which creates the service object for you. If you want to get
|
||||
raw access to this function, you can use the ``raw()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$container['session'] = function ($c) {
|
||||
return new Session($c['session_storage']);
|
||||
};
|
||||
|
||||
$sessionFunction = $container->raw('session');
|
||||
|
||||
.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1
|
25
system/vendor/pimple/pimple/composer.json
vendored
Normal file
25
system/vendor/pimple/pimple/composer.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "pimple/pimple",
|
||||
"type": "library",
|
||||
"description": "Pimple, a simple Dependency Injection Container",
|
||||
"keywords": ["dependency injection", "container"],
|
||||
"homepage": "http://pimple.sensiolabs.org",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Pimple": "src/" }
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
30
system/vendor/pimple/pimple/ext/pimple/.gitignore
vendored
Normal file
30
system/vendor/pimple/pimple/ext/pimple/.gitignore
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
*.sw*
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.fragments
|
||||
Makefile.global
|
||||
Makefile.objects
|
||||
acinclude.m4
|
||||
aclocal.m4
|
||||
build/
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.nice
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.in
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
run-tests.php
|
||||
*.loT
|
||||
.libs/
|
||||
modules/
|
||||
*.la
|
||||
*.lo
|
12
system/vendor/pimple/pimple/ext/pimple/README.md
vendored
Normal file
12
system/vendor/pimple/pimple/ext/pimple/README.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
This is Pimple 2 implemented in C
|
||||
|
||||
* PHP >= 5.3
|
||||
* Not tested under Windows, might work
|
||||
|
||||
Install
|
||||
=======
|
||||
|
||||
> phpize
|
||||
> ./configure
|
||||
> make
|
||||
> make install
|
63
system/vendor/pimple/pimple/ext/pimple/config.m4
vendored
Normal file
63
system/vendor/pimple/pimple/ext/pimple/config.m4
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
dnl $Id$
|
||||
dnl config.m4 for extension pimple
|
||||
|
||||
dnl Comments in this file start with the string 'dnl'.
|
||||
dnl Remove where necessary. This file will not work
|
||||
dnl without editing.
|
||||
|
||||
dnl If your extension references something external, use with:
|
||||
|
||||
dnl PHP_ARG_WITH(pimple, for pimple support,
|
||||
dnl Make sure that the comment is aligned:
|
||||
dnl [ --with-pimple Include pimple support])
|
||||
|
||||
dnl Otherwise use enable:
|
||||
|
||||
PHP_ARG_ENABLE(pimple, whether to enable pimple support,
|
||||
dnl Make sure that the comment is aligned:
|
||||
[ --enable-pimple Enable pimple support])
|
||||
|
||||
if test "$PHP_PIMPLE" != "no"; then
|
||||
dnl Write more examples of tests here...
|
||||
|
||||
dnl # --with-pimple -> check with-path
|
||||
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
|
||||
dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this
|
||||
dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter
|
||||
dnl PIMPLE_DIR=$PHP_PIMPLE
|
||||
dnl else # search default path list
|
||||
dnl AC_MSG_CHECKING([for pimple files in default path])
|
||||
dnl for i in $SEARCH_PATH ; do
|
||||
dnl if test -r $i/$SEARCH_FOR; then
|
||||
dnl PIMPLE_DIR=$i
|
||||
dnl AC_MSG_RESULT(found in $i)
|
||||
dnl fi
|
||||
dnl done
|
||||
dnl fi
|
||||
dnl
|
||||
dnl if test -z "$PIMPLE_DIR"; then
|
||||
dnl AC_MSG_RESULT([not found])
|
||||
dnl AC_MSG_ERROR([Please reinstall the pimple distribution])
|
||||
dnl fi
|
||||
|
||||
dnl # --with-pimple -> add include path
|
||||
dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include)
|
||||
|
||||
dnl # --with-pimple -> check for lib and symbol presence
|
||||
dnl LIBNAME=pimple # you may want to change this
|
||||
dnl LIBSYMBOL=pimple # you most likely want to change this
|
||||
|
||||
dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
|
||||
dnl [
|
||||
dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD)
|
||||
dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ])
|
||||
dnl ],[
|
||||
dnl AC_MSG_ERROR([wrong pimple lib version or lib not found])
|
||||
dnl ],[
|
||||
dnl -L$PIMPLE_DIR/lib -lm
|
||||
dnl ])
|
||||
dnl
|
||||
dnl PHP_SUBST(PIMPLE_SHARED_LIBADD)
|
||||
|
||||
PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared)
|
||||
fi
|
13
system/vendor/pimple/pimple/ext/pimple/config.w32
vendored
Normal file
13
system/vendor/pimple/pimple/ext/pimple/config.w32
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
// If your extension references something external, use ARG_WITH
|
||||
// ARG_WITH("pimple", "for pimple support", "no");
|
||||
|
||||
// Otherwise, use ARG_ENABLE
|
||||
// ARG_ENABLE("pimple", "enable pimple support", "no");
|
||||
|
||||
if (PHP_PIMPLE != "no") {
|
||||
EXTENSION("pimple", "pimple.c");
|
||||
}
|
||||
|
121
system/vendor/pimple/pimple/ext/pimple/php_pimple.h
vendored
Normal file
121
system/vendor/pimple/pimple/ext/pimple/php_pimple.h
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
|
||||
/*
|
||||
* This file is part of Pimple.
|
||||
*
|
||||
* Copyright (c) 2014 Fabien Potencier
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PHP_PIMPLE_H
|
||||
#define PHP_PIMPLE_H
|
||||
|
||||
extern zend_module_entry pimple_module_entry;
|
||||
#define phpext_pimple_ptr &pimple_module_entry
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# define PHP_PIMPLE_API __declspec(dllexport)
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define PHP_PIMPLE_API __attribute__ ((visibility("default")))
|
||||
#else
|
||||
# define PHP_PIMPLE_API
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
#define PIMPLE_VERSION "3.0.2"
|
||||
#define PIMPLE_NS "Pimple"
|
||||
|
||||
#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5
|
||||
#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10
|
||||
|
||||
zend_module_entry *get_module(void);
|
||||
|
||||
PHP_MINIT_FUNCTION(pimple);
|
||||
PHP_MINFO_FUNCTION(pimple);
|
||||
|
||||
PHP_METHOD(Pimple, __construct);
|
||||
PHP_METHOD(Pimple, factory);
|
||||
PHP_METHOD(Pimple, protect);
|
||||
PHP_METHOD(Pimple, raw);
|
||||
PHP_METHOD(Pimple, extend);
|
||||
PHP_METHOD(Pimple, keys);
|
||||
PHP_METHOD(Pimple, register);
|
||||
PHP_METHOD(Pimple, offsetSet);
|
||||
PHP_METHOD(Pimple, offsetUnset);
|
||||
PHP_METHOD(Pimple, offsetGet);
|
||||
PHP_METHOD(Pimple, offsetExists);
|
||||
|
||||
PHP_METHOD(PimpleClosure, invoker);
|
||||
|
||||
typedef struct _pimple_bucket_value {
|
||||
zval *value; /* Must be the first element */
|
||||
zval *raw;
|
||||
zend_object_handle handle_num;
|
||||
enum {
|
||||
PIMPLE_IS_PARAM = 0,
|
||||
PIMPLE_IS_SERVICE = 2
|
||||
} type;
|
||||
zend_bool initialized;
|
||||
zend_fcall_info_cache fcc;
|
||||
} pimple_bucket_value;
|
||||
|
||||
typedef struct _pimple_object {
|
||||
zend_object zobj;
|
||||
HashTable values;
|
||||
HashTable factories;
|
||||
HashTable protected;
|
||||
} pimple_object;
|
||||
|
||||
typedef struct _pimple_closure_object {
|
||||
zend_object zobj;
|
||||
zval *callable;
|
||||
zval *factory;
|
||||
} pimple_closure_object;
|
||||
|
||||
static const char sensiolabs_logo[] = "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHYAAAAUCAMAAABvRTlyAAAAz1BMVEUAAAAAAAAAAAAsThWB5j4AAACD6T8AAACC6D+C6D6C6D+C6D4AAAAAAACC6D4AAAAAAACC6D8AAAAAAAAAAAAAAAAAAAAAAACC6D4AAAAAAAAAAACC6D4AAAAAAAAAAAAAAAAAAAAAAACC6D8AAACC6D4AAAAAAAAAAAAAAAAAAACC6D8AAACC6D6C6D+B6D+C6D+C6D+C6D8AAACC6D6C6D4AAACC6D/K/2KC6D+B6D6C6D6C6D+C6D8sTxUyWRhEeiEAAACC6D+C5z6B6D7drnEVAAAAQXRSTlMAE3oCNSUuDHFHzxaF9UFsu+irX+zlKzYimaJXktyOSFD6BolxqT7QGMMdarMIpuO28r9EolXKgR16OphfXYd4V14GtB4AAAMpSURBVEjHvVSJctowEF1jjME2RziMwUCoMfd9heZqG4n//6buLpJjkmYm03byZmxJa2nf6u2uQcG2bfhqRN4LoTKBzyGDm68M7mAwcOEdjo4zhA/Rf9Go/CVtTgiRhXfIC3EDH8F/eUX1/9KexRo+QgOdtHDsEe/sM7QT32/+K61Z1LFXcXJxN4pTbu1aTQUzuy2PIA0rDo0/0Aa5XFaJvKaVTrubywXvaa1Wq4Vu/Snr3Y7Aojh4VccwykW2N2oQ8wmjyut6+Q1t5ywIG5Npj1sh5E0B7YOzFDjfuRfaOh3O+MbbVNfTWS9COZk3Obd2su5d0a6IU9KLREbw8gEehWSr1r2sPWciXLG38r5NdW0xu9eioU87omjC9yNaMi5GNf6WppVSOqXCFkmCvMB3p9SROLoYQn5pDgQOujA1xjYvqH+plUdkwnmII8VxR/PKYkrfLLomhVlE3b/LhNbNr7hp0H2JaOc4v8dFB58HSsFTSafaqtY1sT3GO8wsy5rhokYPlRJdjPMajyYqTt1EHF/2uqSWQWmAjCUSmQ1MS3g8Btf1XOsy7YIC0CB1b5Xw1Vhba0zbxiCAQLH9TNPmHJXQUtJAN0KcDsoqLxsNvJrJExa7mKIdp2lRE2WexiS4pqWk/0jROlw6K6bV9YOBDGAuqMJ0bnuUKGB0L27bxgRhGEbzihbhxxXaQC88Vkwq8ldCi86RApWUb0Q+4VDosBCc+1s81lUdnBavH4Zp2mm3O44USwOfvSo9oBiwpFg71lMS1VKJLKljS3j9p+fOTvXXlsSNuEv6YPaZda9uRope0VJfKdo7fPiYfSmvFjXQbkhY0d9hCbBWIktRgEDieDhf1N3wbbkmNNgRy8hyl620yGQat/grV3HMpc2HDKTVmOPFz6ylPCKt/nXcAyV260jaAowwIW0YuBzrOgb/KrddZS9OmJaLgpWK4JX2DDuklcLZSDGcn8Vmx9YDNvT6UsjyBApRyFQVX7Vxm9TGxE16nmfRd8/zQoDmggQOTRh5Hv8pMt9Q/L2JmSwkMCE7dA4BuDjHJwfu0Om4QAhOjrN5XkIatglfiN/bUPdCQFjTYgAAAABJRU5ErkJggg==\">";
|
||||
|
||||
static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
|
||||
static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC);
|
||||
|
||||
static void pimple_bucket_dtor(pimple_bucket_value *bucket);
|
||||
static void pimple_free_bucket(pimple_bucket_value *bucket);
|
||||
|
||||
static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC);
|
||||
static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC);
|
||||
static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC);
|
||||
static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC);
|
||||
static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC);
|
||||
static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC);
|
||||
|
||||
static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC);
|
||||
static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC);
|
||||
static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC);
|
||||
static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
|
||||
|
||||
#ifdef ZTS
|
||||
#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v)
|
||||
#else
|
||||
#define PIMPLE_G(v) (pimple_globals.v)
|
||||
#endif
|
||||
|
||||
#endif /* PHP_PIMPLE_H */
|
||||
|
922
system/vendor/pimple/pimple/ext/pimple/pimple.c
vendored
Normal file
922
system/vendor/pimple/pimple/ext/pimple/pimple.c
vendored
Normal file
@@ -0,0 +1,922 @@
|
||||
|
||||
/*
|
||||
* This file is part of Pimple.
|
||||
*
|
||||
* Copyright (c) 2014 Fabien Potencier
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_pimple.h"
|
||||
#include "pimple_compat.h"
|
||||
#include "zend_interfaces.h"
|
||||
#include "zend.h"
|
||||
#include "Zend/zend_closures.h"
|
||||
#include "ext/spl/spl_exceptions.h"
|
||||
#include "Zend/zend_exceptions.h"
|
||||
#include "main/php_output.h"
|
||||
#include "SAPI.h"
|
||||
|
||||
static zend_class_entry *pimple_ce;
|
||||
static zend_object_handlers pimple_object_handlers;
|
||||
static zend_class_entry *pimple_closure_ce;
|
||||
static zend_class_entry *pimple_serviceprovider_ce;
|
||||
static zend_object_handlers pimple_closure_object_handlers;
|
||||
static zend_internal_function pimple_closure_invoker_function;
|
||||
|
||||
#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \
|
||||
ulong index; \
|
||||
pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \
|
||||
|
||||
#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \
|
||||
if (ce != pimple_ce) { \
|
||||
zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \
|
||||
if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \
|
||||
pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \
|
||||
} \
|
||||
zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \
|
||||
if (function->common.scope != ce) { \
|
||||
pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
|
||||
} \
|
||||
zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \
|
||||
if (function->common.scope != ce) { \
|
||||
pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
|
||||
} \
|
||||
zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \
|
||||
if (function->common.scope != ce) { \
|
||||
pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
|
||||
} \
|
||||
} else { \
|
||||
pimple_object_handlers.read_dimension = pimple_object_read_dimension; \
|
||||
pimple_object_handlers.write_dimension = pimple_object_write_dimension; \
|
||||
pimple_object_handlers.has_dimension = pimple_object_has_dimension; \
|
||||
pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \
|
||||
}\
|
||||
} while(0);
|
||||
|
||||
#define PIMPLE_CALL_CB do { \
|
||||
zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \
|
||||
fci.size = sizeof(fci); \
|
||||
fci.object_ptr = retval->fcc.object_ptr; \
|
||||
fci.function_name = retval->value; \
|
||||
fci.no_separation = 1; \
|
||||
fci.retval_ptr_ptr = &retval_ptr_ptr; \
|
||||
\
|
||||
zend_call_function(&fci, &retval->fcc TSRMLS_CC); \
|
||||
efree(fci.params); \
|
||||
if (EG(exception)) { \
|
||||
return EG(uninitialized_zval_ptr); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
|
||||
ZEND_ARG_ARRAY_INFO(0, value, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, offset)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, offset)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, offset)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, offset)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, callable)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, callable)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, id)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, id)
|
||||
ZEND_ARG_INFO(0, callable)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1)
|
||||
ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0)
|
||||
ZEND_ARG_ARRAY_INFO(0, values, 1)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1)
|
||||
ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static const zend_function_entry pimple_ce_functions[] = {
|
||||
PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC)
|
||||
|
||||
PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = {
|
||||
PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register)
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC)
|
||||
{
|
||||
zend_object_std_dtor(&obj->zobj TSRMLS_CC);
|
||||
if (obj->factory) {
|
||||
zval_ptr_dtor(&obj->factory);
|
||||
}
|
||||
if (obj->callable) {
|
||||
zval_ptr_dtor(&obj->callable);
|
||||
}
|
||||
efree(obj);
|
||||
}
|
||||
|
||||
static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC)
|
||||
{
|
||||
zend_hash_destroy(&obj->factories);
|
||||
zend_hash_destroy(&obj->protected);
|
||||
zend_hash_destroy(&obj->values);
|
||||
zend_object_std_dtor(&obj->zobj TSRMLS_CC);
|
||||
efree(obj);
|
||||
}
|
||||
|
||||
static void pimple_free_bucket(pimple_bucket_value *bucket)
|
||||
{
|
||||
if (bucket->raw) {
|
||||
zval_ptr_dtor(&bucket->raw);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
zend_object_value retval;
|
||||
pimple_closure_object *pimple_closure_obj = NULL;
|
||||
|
||||
pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object));
|
||||
ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce);
|
||||
|
||||
pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor;
|
||||
retval.handlers = &pimple_closure_object_handlers;
|
||||
retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC)
|
||||
{
|
||||
zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC)
|
||||
{
|
||||
*zobj_ptr = obj;
|
||||
*ce_ptr = Z_OBJCE_P(obj);
|
||||
*fptr_ptr = (zend_function *)&pimple_closure_invoker_function;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
zend_object_value retval;
|
||||
pimple_object *pimple_obj = NULL;
|
||||
zend_function *function = NULL;
|
||||
|
||||
pimple_obj = emalloc(sizeof(pimple_object));
|
||||
ZEND_OBJ_INIT(&pimple_obj->zobj, ce);
|
||||
|
||||
PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS
|
||||
|
||||
retval.handlers = &pimple_object_handlers;
|
||||
retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC);
|
||||
|
||||
zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
|
||||
zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
|
||||
zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
|
||||
{
|
||||
FETCH_DIM_HANDLERS_VARS
|
||||
|
||||
pimple_bucket_value pimple_value = {0}, *found_value = NULL;
|
||||
ulong hash;
|
||||
|
||||
pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC);
|
||||
|
||||
if (!offset) {/* $p[] = 'foo' when not overloaded */
|
||||
zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
|
||||
Z_ADDREF_P(value);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
|
||||
zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value);
|
||||
if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
|
||||
pimple_free_bucket(&pimple_value);
|
||||
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%s\".", Z_STRVAL_P(offset));
|
||||
return;
|
||||
}
|
||||
if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
|
||||
pimple_free_bucket(&pimple_value);
|
||||
return;
|
||||
}
|
||||
Z_ADDREF_P(value);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
index = (ulong)Z_DVAL_P(offset);
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value);
|
||||
if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) {
|
||||
pimple_free_bucket(&pimple_value);
|
||||
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%ld\".", index);
|
||||
return;
|
||||
}
|
||||
if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) {
|
||||
pimple_free_bucket(&pimple_value);
|
||||
return;
|
||||
}
|
||||
Z_ADDREF_P(value);
|
||||
break;
|
||||
case IS_NULL: /* $p[] = 'foo' when overloaded */
|
||||
zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL);
|
||||
Z_ADDREF_P(value);
|
||||
break;
|
||||
default:
|
||||
pimple_free_bucket(&pimple_value);
|
||||
zend_error(E_WARNING, "Unsupported offset type");
|
||||
}
|
||||
}
|
||||
|
||||
static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC)
|
||||
{
|
||||
FETCH_DIM_HANDLERS_VARS
|
||||
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
|
||||
zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
|
||||
zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
index = (ulong)Z_DVAL_P(offset);
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
zend_hash_index_del(&pimple_obj->values, index);
|
||||
zend_hash_index_del(&pimple_obj->factories, index);
|
||||
zend_hash_index_del(&pimple_obj->protected, index);
|
||||
break;
|
||||
default:
|
||||
zend_error(E_WARNING, "Unsupported offset type");
|
||||
}
|
||||
}
|
||||
|
||||
static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
|
||||
{
|
||||
FETCH_DIM_HANDLERS_VARS
|
||||
|
||||
pimple_bucket_value *retval = NULL;
|
||||
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) {
|
||||
switch (check_empty) {
|
||||
case 0: /* isset */
|
||||
return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */
|
||||
case 1: /* empty */
|
||||
default:
|
||||
return zend_is_true(retval->value);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
index = (ulong)Z_DVAL_P(offset);
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) {
|
||||
switch (check_empty) {
|
||||
case 0: /* isset */
|
||||
return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/
|
||||
case 1: /* empty */
|
||||
default:
|
||||
return zend_is_true(retval->value);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
zend_error(E_WARNING, "Unsupported offset type");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
|
||||
{
|
||||
FETCH_DIM_HANDLERS_VARS
|
||||
|
||||
pimple_bucket_value *retval = NULL;
|
||||
zend_fcall_info fci = {0};
|
||||
zval *retval_ptr_ptr = NULL;
|
||||
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) {
|
||||
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset));
|
||||
return EG(uninitialized_zval_ptr);
|
||||
}
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
index = (ulong)Z_DVAL_P(offset);
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) {
|
||||
return EG(uninitialized_zval_ptr);
|
||||
}
|
||||
break;
|
||||
case IS_NULL: /* $p[][3] = 'foo' first dim access */
|
||||
return EG(uninitialized_zval_ptr);
|
||||
break;
|
||||
default:
|
||||
zend_error(E_WARNING, "Unsupported offset type");
|
||||
return EG(uninitialized_zval_ptr);
|
||||
}
|
||||
|
||||
if(retval->type == PIMPLE_IS_PARAM) {
|
||||
return retval->value;
|
||||
}
|
||||
|
||||
if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) {
|
||||
/* Service is protected, return the value every time */
|
||||
return retval->value;
|
||||
}
|
||||
|
||||
if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) {
|
||||
/* Service is a factory, call it everytime and never cache its result */
|
||||
PIMPLE_CALL_CB
|
||||
Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */
|
||||
return retval_ptr_ptr;
|
||||
}
|
||||
|
||||
if (retval->initialized == 1) {
|
||||
/* Service has already been called, return its cached value */
|
||||
return retval->value;
|
||||
}
|
||||
|
||||
ALLOC_INIT_ZVAL(retval->raw);
|
||||
MAKE_COPY_ZVAL(&retval->value, retval->raw);
|
||||
|
||||
PIMPLE_CALL_CB
|
||||
|
||||
retval->initialized = 1;
|
||||
zval_ptr_dtor(&retval->value);
|
||||
retval->value = retval_ptr_ptr;
|
||||
|
||||
return retval->value;
|
||||
}
|
||||
|
||||
static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
|
||||
{
|
||||
if (Z_TYPE_P(_zval) != IS_OBJECT) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (_pimple_bucket_value->fcc.called_scope) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) {
|
||||
_pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope;
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC)
|
||||
{
|
||||
_pimple_bucket_value->value = _zval;
|
||||
|
||||
if (Z_TYPE_P(_zval) != IS_OBJECT) {
|
||||
return PIMPLE_IS_PARAM;
|
||||
}
|
||||
|
||||
if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) {
|
||||
_pimple_bucket_value->type = PIMPLE_IS_SERVICE;
|
||||
_pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval);
|
||||
}
|
||||
|
||||
return PIMPLE_IS_SERVICE;
|
||||
}
|
||||
|
||||
static void pimple_bucket_dtor(pimple_bucket_value *bucket)
|
||||
{
|
||||
zval_ptr_dtor(&bucket->value);
|
||||
pimple_free_bucket(bucket);
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, protect)
|
||||
{
|
||||
zval *protected = NULL;
|
||||
pimple_object *pobj = NULL;
|
||||
pimple_bucket_value bucket = {0};
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) {
|
||||
pimple_free_bucket(&bucket);
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC);
|
||||
pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
|
||||
Z_ADDREF_P(protected);
|
||||
RETURN_ZVAL(protected, 1 , 0);
|
||||
} else {
|
||||
pimple_free_bucket(&bucket);
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, raw)
|
||||
{
|
||||
zval *offset = NULL;
|
||||
pimple_object *pobj = NULL;
|
||||
pimple_bucket_value *value = NULL;
|
||||
ulong index;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
|
||||
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset));
|
||||
RETURN_NULL();
|
||||
}
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
index = (ulong)Z_DVAL_P(offset);
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
break;
|
||||
case IS_NULL:
|
||||
default:
|
||||
zend_error(E_WARNING, "Unsupported offset type");
|
||||
}
|
||||
|
||||
if (value->raw) {
|
||||
RETVAL_ZVAL(value->raw, 1, 0);
|
||||
} else {
|
||||
RETVAL_ZVAL(value->value, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, extend)
|
||||
{
|
||||
zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL;
|
||||
pimple_bucket_value bucket = {0}, *value = NULL;
|
||||
pimple_object *pobj = NULL;
|
||||
pimple_closure_object *pcobj = NULL;
|
||||
ulong index;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
switch (Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) {
|
||||
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset));
|
||||
RETURN_NULL();
|
||||
}
|
||||
if (value->type != PIMPLE_IS_SERVICE) {
|
||||
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" does not contain an object definition.", Z_STRVAL_P(offset));
|
||||
RETURN_NULL();
|
||||
}
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
case IS_BOOL:
|
||||
case IS_LONG:
|
||||
if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
index = (ulong)Z_DVAL_P(offset);
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) {
|
||||
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" is not defined.", index);
|
||||
RETURN_NULL();
|
||||
}
|
||||
if (value->type != PIMPLE_IS_SERVICE) {
|
||||
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" does not contain an object definition.", index);
|
||||
RETURN_NULL();
|
||||
}
|
||||
break;
|
||||
case IS_NULL:
|
||||
default:
|
||||
zend_error(E_WARNING, "Unsupported offset type");
|
||||
}
|
||||
|
||||
if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) {
|
||||
pimple_free_bucket(&bucket);
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
|
||||
RETURN_NULL();
|
||||
}
|
||||
pimple_free_bucket(&bucket);
|
||||
|
||||
ALLOC_INIT_ZVAL(pimple_closure_obj);
|
||||
object_init_ex(pimple_closure_obj, pimple_closure_ce);
|
||||
|
||||
pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC);
|
||||
pcobj->callable = callable;
|
||||
pcobj->factory = value->value;
|
||||
Z_ADDREF_P(callable);
|
||||
Z_ADDREF_P(value->value);
|
||||
|
||||
if (zend_hash_index_exists(&pobj->factories, value->handle_num)) {
|
||||
pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC);
|
||||
zend_hash_index_del(&pobj->factories, value->handle_num);
|
||||
zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL);
|
||||
Z_ADDREF_P(pimple_closure_obj);
|
||||
}
|
||||
|
||||
pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC);
|
||||
|
||||
RETVAL_ZVAL(pimple_closure_obj, 1, 1);
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, keys)
|
||||
{
|
||||
HashPosition pos;
|
||||
pimple_object *pobj = NULL;
|
||||
zval **value = NULL;
|
||||
zval *endval = NULL;
|
||||
char *str_index = NULL;
|
||||
int str_len;
|
||||
ulong num_index;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pobj = zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
array_init_size(return_value, zend_hash_num_elements(&pobj->values));
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(&pobj->values, &pos);
|
||||
|
||||
while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) {
|
||||
MAKE_STD_ZVAL(endval);
|
||||
switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) {
|
||||
case HASH_KEY_IS_STRING:
|
||||
ZVAL_STRINGL(endval, str_index, str_len - 1, 1);
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
|
||||
break;
|
||||
case HASH_KEY_IS_LONG:
|
||||
ZVAL_LONG(endval, num_index);
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL);
|
||||
break;
|
||||
}
|
||||
zend_hash_move_forward_ex(&pobj->values, &pos);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, factory)
|
||||
{
|
||||
zval *factory = NULL;
|
||||
pimple_object *pobj = NULL;
|
||||
pimple_bucket_value bucket = {0};
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) {
|
||||
pimple_free_bucket(&bucket);
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC);
|
||||
pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) {
|
||||
Z_ADDREF_P(factory);
|
||||
RETURN_ZVAL(factory, 1 , 0);
|
||||
} else {
|
||||
pimple_free_bucket(&bucket);
|
||||
}
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, offsetSet)
|
||||
{
|
||||
zval *offset = NULL, *value = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC);
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, offsetGet)
|
||||
{
|
||||
zval *offset = NULL, *retval = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC);
|
||||
|
||||
RETVAL_ZVAL(retval, 1, 0);
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, offsetUnset)
|
||||
{
|
||||
zval *offset = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pimple_object_unset_dimension(getThis(), offset TSRMLS_CC);
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, offsetExists)
|
||||
{
|
||||
zval *offset = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC));
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, register)
|
||||
{
|
||||
zval *provider;
|
||||
zval **data;
|
||||
zval *retval = NULL;
|
||||
zval key;
|
||||
|
||||
HashTable *array = NULL;
|
||||
HashPosition pos;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETVAL_ZVAL(getThis(), 1, 0);
|
||||
|
||||
zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis());
|
||||
|
||||
if (retval) {
|
||||
zval_ptr_dtor(&retval);
|
||||
}
|
||||
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(array, &pos);
|
||||
|
||||
while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) {
|
||||
zend_hash_get_current_key_zval_ex(array, &key, &pos);
|
||||
pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC);
|
||||
zend_hash_move_forward_ex(array, &pos);
|
||||
}
|
||||
}
|
||||
|
||||
PHP_METHOD(Pimple, __construct)
|
||||
{
|
||||
zval *values = NULL, **pData = NULL, offset;
|
||||
HashPosition pos;
|
||||
char *str_index = NULL;
|
||||
zend_uint str_length;
|
||||
ulong num_index;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE || !values) {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
|
||||
while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) {
|
||||
zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos);
|
||||
zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos);
|
||||
INIT_ZVAL(offset);
|
||||
if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) {
|
||||
ZVAL_LONG(&offset, num_index);
|
||||
} else {
|
||||
ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0);
|
||||
}
|
||||
pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC);
|
||||
zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is PHP code snippet handling extend()s calls :
|
||||
|
||||
$extended = function ($c) use ($callable, $factory) {
|
||||
return $callable($factory($c), $c);
|
||||
};
|
||||
|
||||
*/
|
||||
PHP_METHOD(PimpleClosure, invoker)
|
||||
{
|
||||
pimple_closure_object *pcobj = NULL;
|
||||
zval *arg = NULL, *retval = NULL, *newretval = NULL;
|
||||
zend_fcall_info fci = {0};
|
||||
zval **args[2];
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
pcobj = zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
fci.function_name = pcobj->factory;
|
||||
args[0] = &arg;
|
||||
zend_fcall_info_argp(&fci TSRMLS_CC, 1, args);
|
||||
fci.retval_ptr_ptr = &retval;
|
||||
fci.size = sizeof(fci);
|
||||
|
||||
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
|
||||
efree(fci.params);
|
||||
return; /* Should here return default zval */
|
||||
}
|
||||
|
||||
efree(fci.params);
|
||||
memset(&fci, 0, sizeof(fci));
|
||||
fci.size = sizeof(fci);
|
||||
|
||||
fci.function_name = pcobj->callable;
|
||||
args[0] = &retval;
|
||||
args[1] = &arg;
|
||||
zend_fcall_info_argp(&fci TSRMLS_CC, 2, args);
|
||||
fci.retval_ptr_ptr = &newretval;
|
||||
|
||||
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) {
|
||||
efree(fci.params);
|
||||
zval_ptr_dtor(&retval);
|
||||
return;
|
||||
}
|
||||
|
||||
efree(fci.params);
|
||||
zval_ptr_dtor(&retval);
|
||||
|
||||
RETVAL_ZVAL(newretval, 1 ,1);
|
||||
}
|
||||
|
||||
PHP_MINIT_FUNCTION(pimple)
|
||||
{
|
||||
zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce;
|
||||
INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions);
|
||||
INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL);
|
||||
INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions);
|
||||
|
||||
tmp_pimple_ce.create_object = pimple_object_create;
|
||||
tmp_pimple_closure_ce.create_object = pimple_closure_object_create;
|
||||
|
||||
pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC);
|
||||
zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess);
|
||||
|
||||
pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC);
|
||||
pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS;
|
||||
|
||||
pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC);
|
||||
|
||||
memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers()));
|
||||
pimple_object_handlers = std_object_handlers;
|
||||
pimple_closure_object_handlers.get_closure = pimple_closure_get_closure;
|
||||
|
||||
pimple_closure_invoker_function.function_name = "Pimple closure internal invoker";
|
||||
pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE;
|
||||
pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker);
|
||||
pimple_closure_invoker_function.num_args = 1;
|
||||
pimple_closure_invoker_function.required_num_args = 1;
|
||||
pimple_closure_invoker_function.scope = pimple_closure_ce;
|
||||
pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION;
|
||||
pimple_closure_invoker_function.module = &pimple_module_entry;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_MINFO_FUNCTION(pimple)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled");
|
||||
php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION);
|
||||
php_info_print_table_end();
|
||||
|
||||
php_info_print_box_start(0);
|
||||
php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC);
|
||||
if (!sapi_module.phpinfo_as_text) {
|
||||
php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC);
|
||||
}
|
||||
php_info_print_box_end();
|
||||
}
|
||||
|
||||
zend_module_entry pimple_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"pimple",
|
||||
NULL,
|
||||
PHP_MINIT(pimple),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_MINFO(pimple),
|
||||
PIMPLE_VERSION,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
#ifdef COMPILE_DL_PIMPLE
|
||||
ZEND_GET_MODULE(pimple)
|
||||
#endif
|
81
system/vendor/pimple/pimple/ext/pimple/pimple_compat.h
vendored
Normal file
81
system/vendor/pimple/pimple/ext/pimple/pimple_compat.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
/*
|
||||
* This file is part of Pimple.
|
||||
*
|
||||
* Copyright (c) 2014 Fabien Potencier
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PIMPLE_COMPAT_H_
|
||||
#define PIMPLE_COMPAT_H_
|
||||
|
||||
#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
|
||||
|
||||
#define PHP_5_0_X_API_NO 220040412
|
||||
#define PHP_5_1_X_API_NO 220051025
|
||||
#define PHP_5_2_X_API_NO 220060519
|
||||
#define PHP_5_3_X_API_NO 220090626
|
||||
#define PHP_5_4_X_API_NO 220100525
|
||||
#define PHP_5_5_X_API_NO 220121212
|
||||
#define PHP_5_6_X_API_NO 220131226
|
||||
|
||||
#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO
|
||||
#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
|
||||
|
||||
#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO
|
||||
#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
|
||||
|
||||
#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO
|
||||
#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
|
||||
|
||||
#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO
|
||||
#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
|
||||
|
||||
#if IS_PHP_53
|
||||
#define object_properties_init(obj, ce) do { \
|
||||
zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
#define ZEND_OBJ_INIT(obj, ce) do { \
|
||||
zend_object_std_init(obj, ce TSRMLS_CC); \
|
||||
object_properties_init((obj), (ce)); \
|
||||
} while(0);
|
||||
|
||||
#if IS_PHP_53 || IS_PHP_54
|
||||
static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
|
||||
Bucket *p;
|
||||
|
||||
p = pos ? (*pos) : ht->pInternalPointer;
|
||||
|
||||
if (!p) {
|
||||
Z_TYPE_P(key) = IS_NULL;
|
||||
} else if (p->nKeyLength) {
|
||||
Z_TYPE_P(key) = IS_STRING;
|
||||
Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1);
|
||||
Z_STRLEN_P(key) = p->nKeyLength - 1;
|
||||
} else {
|
||||
Z_TYPE_P(key) = IS_LONG;
|
||||
Z_LVAL_P(key) = p->h;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PIMPLE_COMPAT_H_ */
|
45
system/vendor/pimple/pimple/ext/pimple/tests/001.phpt
vendored
Normal file
45
system/vendor/pimple/pimple/ext/pimple/tests/001.phpt
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
--TEST--
|
||||
Test for read_dim/write_dim handlers
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("pimple")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$p = new Pimple\Container();
|
||||
$p[42] = 'foo';
|
||||
$p['foo'] = 42;
|
||||
|
||||
echo $p[42];
|
||||
echo "\n";
|
||||
echo $p['foo'];
|
||||
echo "\n";
|
||||
try {
|
||||
var_dump($p['nonexistant']);
|
||||
echo "Exception excpected";
|
||||
} catch (InvalidArgumentException $e) { }
|
||||
|
||||
$p[54.2] = 'foo2';
|
||||
echo $p[54];
|
||||
echo "\n";
|
||||
$p[242.99] = 'foo99';
|
||||
echo $p[242];
|
||||
|
||||
echo "\n";
|
||||
|
||||
$p[5] = 'bar';
|
||||
$p[5] = 'baz';
|
||||
echo $p[5];
|
||||
|
||||
echo "\n";
|
||||
|
||||
$p['str'] = 'str';
|
||||
$p['str'] = 'strstr';
|
||||
echo $p['str'];
|
||||
?>
|
||||
|
||||
--EXPECTF--
|
||||
foo
|
||||
42
|
||||
foo2
|
||||
foo99
|
||||
baz
|
||||
strstr
|
15
system/vendor/pimple/pimple/ext/pimple/tests/002.phpt
vendored
Normal file
15
system/vendor/pimple/pimple/ext/pimple/tests/002.phpt
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Test for constructor
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("pimple")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$p = new Pimple\Container();
|
||||
var_dump($p[42]);
|
||||
|
||||
$p = new Pimple\Container(array(42=>'foo'));
|
||||
var_dump($p[42]);
|
||||
?>
|
||||
--EXPECT--
|
||||
NULL
|
||||
string(3) "foo"
|
16
system/vendor/pimple/pimple/ext/pimple/tests/003.phpt
vendored
Normal file
16
system/vendor/pimple/pimple/ext/pimple/tests/003.phpt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Test empty dimensions
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("pimple")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$p = new Pimple\Container();
|
||||
$p[] = 42;
|
||||
var_dump($p[0]);
|
||||
$p[41] = 'foo';
|
||||
$p[] = 'bar';
|
||||
var_dump($p[42]);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(42)
|
||||
string(3) "bar"
|
30
system/vendor/pimple/pimple/ext/pimple/tests/004.phpt
vendored
Normal file
30
system/vendor/pimple/pimple/ext/pimple/tests/004.phpt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Test has/unset dim handlers
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("pimple")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$p = new Pimple\Container();
|
||||
$p[] = 42;
|
||||
var_dump($p[0]);
|
||||
unset($p[0]);
|
||||
var_dump($p[0]);
|
||||
$p['foo'] = 'bar';
|
||||
var_dump(isset($p['foo']));
|
||||
unset($p['foo']);
|
||||
try {
|
||||
var_dump($p['foo']);
|
||||
echo "Excpected exception";
|
||||
} catch (InvalidArgumentException $e) { }
|
||||
var_dump(isset($p['bar']));
|
||||
$p['bar'] = NULL;
|
||||
var_dump(isset($p['bar']));
|
||||
var_dump(empty($p['bar']));
|
||||
?>
|
||||
--EXPECT--
|
||||
int(42)
|
||||
NULL
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
27
system/vendor/pimple/pimple/ext/pimple/tests/005.phpt
vendored
Normal file
27
system/vendor/pimple/pimple/ext/pimple/tests/005.phpt
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
--TEST--
|
||||
Test simple class inheritance
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("pimple")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
class MyPimple extends Pimple\Container
|
||||
{
|
||||
public $someAttr = 'fooAttr';
|
||||
|
||||
public function offsetget($o)
|
||||
{
|
||||
var_dump("hit");
|
||||
return parent::offsetget($o);
|
||||
}
|
||||
}
|
||||
|
||||
$p = new MyPimple;
|
||||
$p[42] = 'foo';
|
||||
echo $p[42];
|
||||
echo "\n";
|
||||
echo $p->someAttr;
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "hit"
|
||||
foo
|
||||
fooAttr
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user