mirror of
https://github.com/standardebooks/web.git
synced 2025-07-12 09:32:24 -04:00
Add Composer autoloading functions and PHPStan for testing
This commit is contained in:
parent
e198c4db65
commit
f5d7d4e02a
1518 changed files with 169063 additions and 30 deletions
39
vendor/nette/robot-loader/composer.json
vendored
Normal file
39
vendor/nette/robot-loader/composer.json
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "nette/robot-loader",
|
||||
"description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.",
|
||||
"keywords": ["nette", "autoload", "class", "trait", "interface"],
|
||||
"homepage": "https://nette.org",
|
||||
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.0",
|
||||
"ext-tokenizer": "*",
|
||||
"nette/finder": "^2.3 || ^3.0",
|
||||
"nette/utils": "^2.4 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.0",
|
||||
"tracy/tracy": "^2.3"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/nette": "<2.2"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": ["src/"]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
}
|
||||
}
|
33
vendor/nette/robot-loader/contributing.md
vendored
Normal file
33
vendor/nette/robot-loader/contributing.md
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
How to contribute & use the issue tracker
|
||||
=========================================
|
||||
|
||||
Nette welcomes your contributions. There are several ways to help out:
|
||||
|
||||
* Create an issue on GitHub, if you have found a bug
|
||||
* Write test cases for open bug issues
|
||||
* Write fixes for open bug/feature issues, preferably with test cases included
|
||||
* Contribute to the [documentation](https://nette.org/en/writing)
|
||||
|
||||
Issues
|
||||
------
|
||||
|
||||
Please **do not use the issue tracker to ask questions**. We will be happy to help you
|
||||
on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette).
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more
|
||||
information. Please try to be as detailed as possible in your report.
|
||||
|
||||
**Feature requests** are welcome. But take a moment to find out whether your idea
|
||||
fits with the scope and aims of the project. It's up to *you* to make a strong
|
||||
case to convince the project's developers of the merits of this feature.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing).
|
||||
|
||||
The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them.
|
||||
|
||||
Please do not fix whitespace, format code, or make a purely cosmetic patch.
|
||||
|
||||
Thanks! :heart:
|
60
vendor/nette/robot-loader/license.md
vendored
Normal file
60
vendor/nette/robot-loader/license.md
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
Licenses
|
||||
========
|
||||
|
||||
Good news! You may use Nette Framework under the terms of either
|
||||
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
|
||||
|
||||
The BSD License is recommended for most projects. It is easy to understand and it
|
||||
places almost no restrictions on what you can do with the framework. If the GPL
|
||||
fits better to your project, you can use the framework under this license.
|
||||
|
||||
You don't have to notify anyone which license you are using. You can freely
|
||||
use Nette Framework in commercial projects as long as the copyright header
|
||||
remains intact.
|
||||
|
||||
Please be advised that the name "Nette Framework" is a protected trademark and its
|
||||
usage has some limitations. So please do not use word "Nette" in the name of your
|
||||
project or top-level domain, and choose a name that stands on its own merits.
|
||||
If your stuff is good, it will not take long to establish a reputation for yourselves.
|
||||
|
||||
|
||||
New BSD License
|
||||
---------------
|
||||
|
||||
Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
|
||||
All 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.
|
||||
|
||||
* Neither the name of "Nette Framework" nor the names of its contributors
|
||||
may 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.
|
||||
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
GPL licenses are very very long, so instead of including them here we offer
|
||||
you URLs with full text:
|
||||
|
||||
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
|
||||
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
|
78
vendor/nette/robot-loader/readme.md
vendored
Normal file
78
vendor/nette/robot-loader/readme.md
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
RobotLoader: comfortable autoloading
|
||||
====================================
|
||||
|
||||
[](https://packagist.org/packages/nette/robot-loader)
|
||||
[](https://travis-ci.org/nette/robot-loader)
|
||||
[](https://coveralls.io/github/nette/robot-loader?branch=master)
|
||||
[](https://github.com/nette/robot-loader/releases)
|
||||
[](https://github.com/nette/robot-loader/blob/master/license.md)
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
RobotLoader is a tool that gives you comfort of automated class loading for your entire application including third-party libraries.
|
||||
|
||||
- get rid of all `require`
|
||||
- only necessary scripts are loaded
|
||||
- requires no strict file naming conventions
|
||||
- allows more classes in single file
|
||||
|
||||
RobotLoader is extremely comfortable and addictive!
|
||||
|
||||
If you like Nette, **[please make a donation now](https://nette.org/donate)**. Thank you!
|
||||
|
||||
So we can forget about those famous code blocks:
|
||||
|
||||
```php
|
||||
require_once 'Utils/Page.php';
|
||||
require_once 'Utils/Style.php';
|
||||
require_once 'Utils/Paginator.php';
|
||||
...
|
||||
```
|
||||
|
||||
Like the Google robot crawls and indexes websites, RobotLoader crawls all PHP scripts and records what classes and interfaces were found in them.
|
||||
These records are then saved in cache and used during all subsequent requests.
|
||||
|
||||
Documentation can be found on the [website](https://doc.nette.org/robotloader).
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The recommended way to install is via Composer:
|
||||
|
||||
```
|
||||
composer require nette/robot-loader
|
||||
```
|
||||
|
||||
It requires PHP version 5.6 and supports PHP up to 7.2.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
You just need to specifiy what directories to index and where to save the cache:
|
||||
|
||||
```php
|
||||
$loader = new Nette\Loaders\RobotLoader;
|
||||
|
||||
// Add directories for RobotLoader to index
|
||||
$loader->addDirectory(__DIR__ . '/app');
|
||||
$loader->addDirectory(__DIR__ . '/libs');
|
||||
|
||||
// And set caching to the 'temp' directory
|
||||
$loader->setTempDirectory(__DIR__ . '/temp');
|
||||
$loader->register(); // Run the RobotLoader
|
||||
```
|
||||
|
||||
And that's all. From now on, you don't need to use `require`. Great, isn't it?
|
||||
|
||||
When RobotLoader encounters duplicate class name during indexing, it throws an exception and informs you about it.
|
||||
|
||||
The `$loader->setAutoRefresh(true or false)` determines whether RobotLoader should reindex files if asked for nonexistent class.
|
||||
This feature should be disabled on production server.
|
||||
|
||||
If you want RobotLoader to skip some directory, use `$loader->excludeDirectory('temp')`.
|
||||
|
||||
By default, RobotLoader reports errors in PHP files by throwing exception `ParseError` (since PHP 7.0). It can be disabled via `$loader->reportParseErrors(false)`.
|
471
vendor/nette/robot-loader/src/RobotLoader/RobotLoader.php
vendored
Normal file
471
vendor/nette/robot-loader/src/RobotLoader/RobotLoader.php
vendored
Normal file
|
@ -0,0 +1,471 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Nette Framework (https://nette.org)
|
||||
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
namespace Nette\Loaders;
|
||||
|
||||
use Nette;
|
||||
use SplFileInfo;
|
||||
|
||||
|
||||
/**
|
||||
* Nette auto loader is responsible for loading classes and interfaces.
|
||||
*
|
||||
* <code>
|
||||
* $loader = new Nette\Loaders\RobotLoader;
|
||||
* $loader->addDirectory('app');
|
||||
* $loader->excludeDirectory('app/exclude');
|
||||
* $loader->setTempDirectory('temp');
|
||||
* $loader->register();
|
||||
* </code>
|
||||
*/
|
||||
class RobotLoader
|
||||
{
|
||||
use Nette\SmartObject;
|
||||
|
||||
const RETRY_LIMIT = 3;
|
||||
|
||||
/** @var array comma separated wildcards */
|
||||
public $ignoreDirs = ['.*', '*.old', '*.bak', '*.tmp', 'temp'];
|
||||
|
||||
/** @var array comma separated wildcards */
|
||||
public $acceptFiles = ['*.php'];
|
||||
|
||||
/** @var bool */
|
||||
private $autoRebuild = true;
|
||||
|
||||
/** @var bool */
|
||||
private $reportParseErrors = true;
|
||||
|
||||
/** @var array */
|
||||
private $scanPaths = [];
|
||||
|
||||
/** @var array */
|
||||
private $excludeDirs = [];
|
||||
|
||||
/** @var array of class => [file, time] */
|
||||
private $classes = [];
|
||||
|
||||
/** @var bool */
|
||||
private $refreshed = false;
|
||||
|
||||
/** @var array of missing classes */
|
||||
private $missing = [];
|
||||
|
||||
/** @var string|null */
|
||||
private $tempDirectory;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (!extension_loaded('tokenizer')) {
|
||||
throw new Nette\NotSupportedException('PHP extension Tokenizer is not loaded.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register autoloader.
|
||||
* @param bool $prepend
|
||||
* @return static
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
$this->loadCache();
|
||||
spl_autoload_register([$this, 'tryLoad'], true, $prepend);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles autoloading of classes, interfaces or traits.
|
||||
* @param string $type
|
||||
* @return void
|
||||
*/
|
||||
public function tryLoad($type)
|
||||
{
|
||||
$type = ltrim($type, '\\'); // PHP namespace bug #49143
|
||||
$info = isset($this->classes[$type]) ? $this->classes[$type] : null;
|
||||
|
||||
if ($this->autoRebuild) {
|
||||
if (!$info || !is_file($info['file'])) {
|
||||
$missing = &$this->missing[$type];
|
||||
$missing++;
|
||||
if (!$this->refreshed && $missing <= self::RETRY_LIMIT) {
|
||||
$this->refresh();
|
||||
$this->saveCache();
|
||||
} elseif ($info) {
|
||||
unset($this->classes[$type]);
|
||||
$this->saveCache();
|
||||
}
|
||||
|
||||
} elseif (!$this->refreshed && filemtime($info['file']) !== $info['time']) {
|
||||
$this->updateFile($info['file']);
|
||||
if (empty($this->classes[$type])) {
|
||||
$this->missing[$type] = 0;
|
||||
}
|
||||
$this->saveCache();
|
||||
}
|
||||
$info = isset($this->classes[$type]) ? $this->classes[$type] : null;
|
||||
}
|
||||
|
||||
if ($info) {
|
||||
call_user_func(function ($file) { require $file; }, $info['file']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add path or paths to list.
|
||||
* @param string|string[] $path absolute path
|
||||
* @return static
|
||||
*/
|
||||
public function addDirectory($path)
|
||||
{
|
||||
$this->scanPaths = array_merge($this->scanPaths, (array) $path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function reportParseErrors($on = true)
|
||||
{
|
||||
$this->reportParseErrors = (bool) $on;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Excludes path or paths from list.
|
||||
* @param string|string[] $path absolute path
|
||||
* @return static
|
||||
*/
|
||||
public function excludeDirectory($path)
|
||||
{
|
||||
$this->excludeDirs = array_merge($this->excludeDirs, (array) $path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array of class => filename
|
||||
*/
|
||||
public function getIndexedClasses()
|
||||
{
|
||||
$res = [];
|
||||
foreach ($this->classes as $class => $info) {
|
||||
$res[$class] = $info['file'];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rebuilds class list cache.
|
||||
* @return void
|
||||
*/
|
||||
public function rebuild()
|
||||
{
|
||||
$this->refresh();
|
||||
if ($this->tempDirectory) {
|
||||
$this->saveCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refreshes class list.
|
||||
* @return void
|
||||
*/
|
||||
private function refresh()
|
||||
{
|
||||
$this->refreshed = true; // prevents calling refresh() or updateFile() in tryLoad()
|
||||
$files = [];
|
||||
foreach ($this->classes as $class => $info) {
|
||||
$files[$info['file']]['time'] = $info['time'];
|
||||
$files[$info['file']]['classes'][] = $class;
|
||||
}
|
||||
|
||||
$this->classes = [];
|
||||
foreach ($this->scanPaths as $path) {
|
||||
foreach (is_file($path) ? [new SplFileInfo($path)] : $this->createFileIterator($path) as $file) {
|
||||
$file = $file->getPathname();
|
||||
if (isset($files[$file]) && $files[$file]['time'] == filemtime($file)) {
|
||||
$classes = $files[$file]['classes'];
|
||||
} else {
|
||||
$classes = $this->scanPhp($file);
|
||||
}
|
||||
$files[$file] = ['classes' => [], 'time' => filemtime($file)];
|
||||
|
||||
foreach ($classes as $class) {
|
||||
$info = &$this->classes[$class];
|
||||
if (isset($info['file'])) {
|
||||
throw new Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
|
||||
}
|
||||
$info = ['file' => $file, 'time' => filemtime($file)];
|
||||
unset($this->missing[$class]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an iterator scaning directory for PHP files, subdirectories and 'netterobots.txt' files.
|
||||
* @return Nette\Utils\Finder
|
||||
* @throws Nette\IOException if path is not found
|
||||
*/
|
||||
private function createFileIterator($dir)
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
throw new Nette\IOException("File or directory '$dir' not found.");
|
||||
}
|
||||
|
||||
$ignoreDirs = is_array($this->ignoreDirs) ? $this->ignoreDirs : preg_split('#[,\s]+#', $this->ignoreDirs);
|
||||
$disallow = [];
|
||||
foreach (array_merge($ignoreDirs, $this->excludeDirs) as $item) {
|
||||
if ($item = realpath($item)) {
|
||||
$disallow[str_replace('\\', '/', $item)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$iterator = Nette\Utils\Finder::findFiles(is_array($this->acceptFiles) ? $this->acceptFiles : preg_split('#[,\s]+#', $this->acceptFiles))
|
||||
->filter(function (SplFileInfo $file) use (&$disallow) {
|
||||
return !isset($disallow[str_replace('\\', '/', $file->getRealPath())]);
|
||||
})
|
||||
->from($dir)
|
||||
->exclude($ignoreDirs)
|
||||
->filter($filter = function (SplFileInfo $dir) use (&$disallow) {
|
||||
$path = str_replace('\\', '/', $dir->getRealPath());
|
||||
if (is_file("$path/netterobots.txt")) {
|
||||
foreach (file("$path/netterobots.txt") as $s) {
|
||||
if (preg_match('#^(?:disallow\\s*:)?\\s*(\\S+)#i', $s, $matches)) {
|
||||
$disallow[$path . rtrim('/' . ltrim($matches[1], '/'), '/')] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !isset($disallow[$path]);
|
||||
});
|
||||
|
||||
$filter(new SplFileInfo($dir));
|
||||
return $iterator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function updateFile($file)
|
||||
{
|
||||
foreach ($this->classes as $class => $info) {
|
||||
if (isset($info['file']) && $info['file'] === $file) {
|
||||
unset($this->classes[$class]);
|
||||
}
|
||||
}
|
||||
|
||||
$classes = is_file($file) ? $this->scanPhp($file) : [];
|
||||
foreach ($classes as $class) {
|
||||
$info = &$this->classes[$class];
|
||||
if (isset($info['file']) && @filemtime($info['file']) !== $info['time']) { // @ file may not exists
|
||||
$this->updateFile($info['file']);
|
||||
$info = &$this->classes[$class];
|
||||
}
|
||||
if (isset($info['file'])) {
|
||||
throw new Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
|
||||
}
|
||||
$info = ['file' => $file, 'time' => filemtime($file)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches classes, interfaces and traits in PHP file.
|
||||
* @param string $file
|
||||
* @return string[]
|
||||
*/
|
||||
private function scanPhp($file)
|
||||
{
|
||||
$code = file_get_contents($file);
|
||||
$expected = false;
|
||||
$namespace = '';
|
||||
$level = $minLevel = 0;
|
||||
$classes = [];
|
||||
|
||||
if (preg_match('#//nette' . 'loader=(\S*)#', $code, $matches)) {
|
||||
foreach (explode(',', $matches[1]) as $name) {
|
||||
$classes[] = $name;
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$tokens = PHP_VERSION_ID >= 70000
|
||||
? token_get_all($code, TOKEN_PARSE)
|
||||
: @token_get_all($code); // @ can be corrupted or can use newer syntax
|
||||
} catch (\ParseError $e) {
|
||||
if ($this->reportParseErrors) {
|
||||
$rp = new \ReflectionProperty($e, 'file');
|
||||
$rp->setAccessible(true);
|
||||
$rp->setValue($e, $file);
|
||||
throw $e;
|
||||
}
|
||||
$tokens = [];
|
||||
}
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
if (is_array($token)) {
|
||||
switch ($token[0]) {
|
||||
case T_COMMENT:
|
||||
case T_DOC_COMMENT:
|
||||
case T_WHITESPACE:
|
||||
continue 2;
|
||||
|
||||
case T_NS_SEPARATOR:
|
||||
case T_STRING:
|
||||
if ($expected) {
|
||||
$name .= $token[1];
|
||||
}
|
||||
continue 2;
|
||||
|
||||
case T_NAMESPACE:
|
||||
case T_CLASS:
|
||||
case T_INTERFACE:
|
||||
case T_TRAIT:
|
||||
$expected = $token[0];
|
||||
$name = '';
|
||||
continue 2;
|
||||
case T_CURLY_OPEN:
|
||||
case T_DOLLAR_OPEN_CURLY_BRACES:
|
||||
$level++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expected) {
|
||||
switch ($expected) {
|
||||
case T_CLASS:
|
||||
case T_INTERFACE:
|
||||
case T_TRAIT:
|
||||
if ($name && $level === $minLevel) {
|
||||
$classes[] = $namespace . $name;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_NAMESPACE:
|
||||
$namespace = $name ? $name . '\\' : '';
|
||||
$minLevel = $token === '{' ? 1 : 0;
|
||||
}
|
||||
|
||||
$expected = null;
|
||||
}
|
||||
|
||||
if ($token === '{') {
|
||||
$level++;
|
||||
} elseif ($token === '}') {
|
||||
$level--;
|
||||
}
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
|
||||
/********************* caching ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Sets auto-refresh mode.
|
||||
* @return static
|
||||
*/
|
||||
public function setAutoRefresh($on = true)
|
||||
{
|
||||
$this->autoRebuild = (bool) $on;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets path to temporary directory.
|
||||
* @return static
|
||||
*/
|
||||
public function setTempDirectory($dir)
|
||||
{
|
||||
Nette\Utils\FileSystem::createDir($dir);
|
||||
$this->tempDirectory = $dir;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads class list from cache.
|
||||
* @return void
|
||||
*/
|
||||
private function loadCache()
|
||||
{
|
||||
$file = $this->getCacheFile();
|
||||
list($this->classes, $this->missing) = @include $file; // @ file may not exist
|
||||
if (is_array($this->classes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$handle = fopen("$file.lock", 'c+');
|
||||
if (!$handle || !flock($handle, LOCK_EX)) {
|
||||
throw new \RuntimeException("Unable to create or acquire exclusive lock on file '$file.lock'.");
|
||||
}
|
||||
|
||||
list($this->classes, $this->missing) = @include $file; // @ file may not exist
|
||||
if (!is_array($this->classes)) {
|
||||
$this->classes = [];
|
||||
$this->refresh();
|
||||
$this->saveCache();
|
||||
}
|
||||
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
@unlink("$file.lock"); // @ file may become locked on Windows
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes class list to cache.
|
||||
* @return void
|
||||
*/
|
||||
private function saveCache()
|
||||
{
|
||||
$file = $this->getCacheFile();
|
||||
$tempFile = $file . uniqid('', true) . '.tmp';
|
||||
$code = "<?php\nreturn " . var_export([$this->classes, $this->missing], true) . ";\n";
|
||||
if (file_put_contents($tempFile, $code) !== strlen($code) || !rename($tempFile, $file)) {
|
||||
@unlink($tempFile); // @ - file may not exist
|
||||
throw new \RuntimeException("Unable to create '$file'.");
|
||||
}
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
@opcache_invalidate($file, true); // @ can be restricted
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getCacheFile()
|
||||
{
|
||||
if (!$this->tempDirectory) {
|
||||
throw new \LogicException('Set path to temporary directory using setTempDirectory().');
|
||||
}
|
||||
return $this->tempDirectory . '/' . md5(serialize($this->getCacheKey())) . '.php';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getCacheKey()
|
||||
{
|
||||
return [$this->ignoreDirs, $this->acceptFiles, $this->scanPaths, $this->excludeDirs];
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue