Maslosoft Addendum API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
<?php
/**
* This software package is licensed under AGPL, Commercial license.
*
* @package maslosoft/addendum
* @licence AGPL, Commercial
* @copyright Copyright (c) Piotr Masełkowski <pmaselkowski@gmail.com> (Meta container, further improvements, bugfixes)
* @copyright Copyright (c) Maslosoft (Meta container, further improvements, bugfixes)
* @copyright Copyright (c) Jan Suchal (Original version, builder, parser)
* @link https://maslosoft.com/addendum/ - maslosoft addendum
* @link https://code.google.com/p/addendum/ - original addendum project
*/
namespace Maslosoft\Addendum\Utilities;
use DirectoryIterator;
/**
* FileWalker
*
* This walks recursivelly on symlinks too, with loop detection.
* Will process only files starting with Capital Letters.
*
* Will skip files with identical content.
*
* This class is meant to replace AnnotationUtility::fileWalker method.
*
* @author Piotr Maselkowski <pmaselkowski at gmail.com>
*/
class FileWalker
{
/**
* Pahts to scan
* @var string[]
*/
private $paths = [];
/**
* Dirs to ignore
* @var string[]
*/
private $ignoreDirs = [];
/**
* Patterns to match for annotations
* @var string[]
*/
private $patterns = [];
/**
* Callback to execute on file
* @var callback
*/
private $callback;
/**
* List of visited real paths
* @var bool[]
*/
private $visited = [];
/**
* Whether sum was parsed. This is to avoid duplicated files parsing.
* @var bool[]
*/
private $sum = [];
public function __construct($annotations, $callback, $paths, $ignoreDirs = [])
{
$this->paths = $paths;
$this->ignoreDirs = $ignoreDirs;
$this->callback = $callback;
$this->patterns = [];
foreach ($annotations as $annotation)
{
$annotation = preg_replace('~^@~', '', $annotation);
$this->patterns[] = sprintf('~@%s~', $annotation);
}
}
public function walk()
{
foreach ($this->paths as $path)
{
$this->scan($path);
}
}
private function scan($path)
{
// Check if should be visited. Using realpath prevents symlink loops.
$real = realpath($path);
if (!empty($this->visited[$real]))
{
return;
}
// Mark real path as visited
$this->visited[$real] = true;
// Scan real path
$iterator = new DirectoryIterator($real);
foreach ($iterator as $info)
{
if ($info->isDot())
{
continue;
}
// Recurse, loop prevention check is on top of this function
if ($info->isDir())
{
// Skip ignored dirs,
// this is might be important when scanning nested projects
// containning it's own vendors, cache paths etc.
if (in_array($info->getBasename(), $this->ignoreDirs))
{
continue;
}
$this->scan($info->getPathname());
continue;
}
$file = $info->getPathname();
// Check if should be processed
if (!empty($this->visited[$file]))
{
continue;
}
// Mark as processed
$this->visited[$file] = true;
// Only php
if (!preg_match('~^.+\.php$~i', $file))
{
continue;
}
// Only starting with capital letter
if (!preg_match('~^[A-Z]~', $info->getBasename()))
{
continue;
}
// If patterns are empty, parse every file
$parse = empty($this->patterns);
if (is_readable($file))
{
$contents = file_get_contents($file);
}
else
{
// TODO Log this
continue;
}
// Check for file checksum
$sum = md5($contents);
// Check if should be processed
if (!empty($this->sum[$sum]))
{
continue;
}
$this->sum[$sum] = true;
foreach ($this->patterns as $pattern)
{
if ($parse)
{
continue;
}
if (preg_match($pattern, $contents))
{
$parse = true;
}
}
if (!$parse)
{
continue;
}
call_user_func($this->callback, $file, $contents);
}
}
}
API documentation generated by ApiGen