These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * phpDocumentor |
||
4 | * |
||
5 | * PHP Version 5.3 |
||
6 | * |
||
7 | * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com) |
||
8 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
9 | * @link http://phpdoc.org |
||
10 | */ |
||
11 | |||
12 | namespace phpDocumentor; |
||
13 | |||
14 | use Cilex\Application as Cilex; |
||
15 | use Cilex\Provider\JmsSerializerServiceProvider; |
||
16 | use Cilex\Provider\MonologServiceProvider; |
||
17 | use Cilex\Provider\ValidatorServiceProvider; |
||
18 | use Composer\Autoload\ClassLoader; |
||
19 | use Monolog\ErrorHandler; |
||
20 | use Monolog\Handler\NullHandler; |
||
21 | use Monolog\Handler\StreamHandler; |
||
22 | use Monolog\Logger; |
||
23 | use phpDocumentor\Command\Helper\ConfigurationHelper; |
||
24 | use phpDocumentor\Command\Helper\LoggerHelper; |
||
25 | use phpDocumentor\Console\Input\ArgvInput; |
||
26 | use Symfony\Component\Console\Application as ConsoleApplication; |
||
27 | use Symfony\Component\Console\Input\InputInterface; |
||
28 | use Symfony\Component\Console\Output\OutputInterface; |
||
29 | use Symfony\Component\Console\Shell; |
||
30 | use Symfony\Component\Stopwatch\Stopwatch; |
||
31 | |||
32 | /** |
||
33 | * Application class for phpDocumentor. |
||
34 | * |
||
35 | * Can be used as bootstrap when the run method is not invoked. |
||
36 | */ |
||
37 | class Application extends Cilex |
||
38 | { |
||
39 | /** @var string $VERSION represents the version of phpDocumentor as stored in /VERSION */ |
||
40 | public static $VERSION; |
||
41 | |||
42 | /** |
||
43 | * Initializes all components used by phpDocumentor. |
||
44 | * |
||
45 | * @param ClassLoader $autoloader |
||
46 | * @param array $values |
||
47 | */ |
||
48 | 14 | public function __construct($autoloader = null, array $values = array()) |
|
49 | { |
||
50 | 14 | $this->defineIniSettings(); |
|
51 | |||
52 | 14 | self::$VERSION = strpos('@package_version@', '@') === 0 |
|
53 | 14 | ? trim(file_get_contents(__DIR__ . '/../../VERSION')) |
|
54 | 14 | : '@package_version@'; |
|
55 | |||
56 | 14 | parent::__construct('phpDocumentor', self::$VERSION, $values); |
|
57 | |||
58 | 14 | $this['kernel.timer.start'] = time(); |
|
59 | 14 | $this['kernel.stopwatch'] = function () { |
|
60 | 14 | return new Stopwatch(); |
|
61 | }; |
||
62 | |||
63 | 14 | $this['autoloader'] = $autoloader; |
|
64 | |||
65 | 14 | $this->register(new JmsSerializerServiceProvider()); |
|
66 | 14 | $this->register(new Configuration\ServiceProvider()); |
|
67 | |||
68 | 14 | $this->addEventDispatcher(); |
|
69 | 14 | $this->addLogging(); |
|
70 | |||
71 | 14 | $this->register(new Translator\ServiceProvider()); |
|
72 | 14 | $this->register(new Descriptor\ServiceProvider()); |
|
73 | 14 | $this->register(new Partials\ServiceProvider()); |
|
74 | 14 | $this->register(new Parser\ServiceProvider()); |
|
75 | 14 | $this->register(new Transformer\ServiceProvider()); |
|
76 | 14 | $this->register(new Plugin\ServiceProvider()); |
|
77 | |||
78 | 14 | $this->addCommandsForProjectNamespace(); |
|
79 | |||
80 | 14 | if (\Phar::running()) { |
|
81 | $this->addCommandsForPharNamespace(); |
||
82 | } |
||
83 | 14 | } |
|
84 | |||
85 | /** |
||
86 | * Removes all logging handlers and replaces them with handlers that can write to the given logPath and level. |
||
87 | * |
||
88 | * @param Logger $logger The logger instance that needs to be configured. |
||
89 | * @param integer $level The minimum level that will be written to the normal logfile; matches one of the |
||
90 | * constants in {@see \Monolog\Logger}. |
||
91 | * @param string $logPath The full path where the normal log file needs to be written. |
||
92 | * |
||
93 | * @return void |
||
94 | */ |
||
95 | 11 | public function configureLogger($logger, $level, $logPath = null) |
|
96 | { |
||
97 | /** @var Logger $monolog */ |
||
98 | 11 | $monolog = $logger; |
|
99 | |||
100 | switch ($level) { |
||
101 | 11 | case 'emergency': |
|
102 | 11 | case 'emerg': |
|
103 | 2 | $level = Logger::EMERGENCY; |
|
104 | 2 | break; |
|
105 | 11 | case 'alert': |
|
106 | 1 | $level = Logger::ALERT; |
|
107 | 1 | break; |
|
108 | 11 | case 'critical': |
|
109 | 11 | case 'crit': |
|
110 | 1 | $level = Logger::CRITICAL; |
|
111 | 1 | break; |
|
112 | 11 | case 'error': |
|
113 | 6 | case 'err': |
|
114 | 11 | $level = Logger::ERROR; |
|
115 | 11 | break; |
|
116 | 5 | case 'warning': |
|
117 | 4 | case 'warn': |
|
118 | 2 | $level = Logger::WARNING; |
|
119 | 2 | break; |
|
120 | 3 | case 'notice': |
|
121 | 1 | $level = Logger::NOTICE; |
|
122 | 1 | break; |
|
123 | 2 | case 'info': |
|
124 | 1 | $level = Logger::INFO; |
|
125 | 1 | break; |
|
126 | 1 | case 'debug': |
|
127 | 1 | $level = Logger::DEBUG; |
|
128 | 1 | break; |
|
129 | } |
||
130 | |||
131 | 11 | $this['monolog.level'] = $level; |
|
132 | 11 | if ($logPath) { |
|
133 | $logPath = str_replace( |
||
134 | array('{APP_ROOT}', '{DATE}'), |
||
135 | array(realpath(__DIR__ . '/../..'), $this['kernel.timer.start']), |
||
136 | $logPath |
||
137 | ); |
||
138 | $this['monolog.logfile'] = $logPath; |
||
139 | } |
||
140 | |||
141 | // remove all handlers from the stack |
||
142 | try { |
||
143 | 11 | while ($monolog->popHandler()) { |
|
144 | } |
||
145 | 11 | } catch (\LogicException $e) { |
|
146 | // popHandler throws an exception when you try to pop the empty stack; to us this is not an |
||
147 | // error but an indication that the handler stack is empty. |
||
148 | } |
||
149 | |||
150 | 11 | if ($level === 'quiet') { |
|
151 | $monolog->pushHandler(new NullHandler()); |
||
152 | |||
153 | return; |
||
154 | } |
||
155 | |||
156 | // set our new handlers |
||
157 | 11 | if ($logPath) { |
|
158 | $monolog->pushHandler(new StreamHandler($logPath, $level)); |
||
159 | } else { |
||
160 | 11 | $monolog->pushHandler(new StreamHandler('php://stdout', $level)); |
|
161 | } |
||
162 | 11 | } |
|
163 | |||
164 | /** |
||
165 | * @param null|InputInterface $input |
||
166 | * @param null|OutputInterface $output |
||
167 | * @return mixed |
||
168 | */ |
||
169 | public function run(InputInterface $input = null, OutputInterface $output = null) |
||
170 | { |
||
171 | /** @var ConsoleApplication $app */ |
||
172 | $app = $this['console']; |
||
173 | $app->setAutoExit(false); |
||
174 | |||
175 | if ($output === null) { |
||
176 | $output = new Console\Output\Output(); |
||
177 | $output->setLogger($this['monolog']); |
||
178 | } |
||
179 | |||
180 | return parent::run(new ArgvInput(), $output); |
||
181 | } |
||
182 | |||
183 | |||
184 | /** |
||
185 | * Adjust php.ini settings. |
||
186 | * |
||
187 | * @return void |
||
188 | */ |
||
189 | 1 | protected function defineIniSettings() |
|
190 | { |
||
191 | 1 | $this->setTimezone(); |
|
192 | 1 | ini_set('memory_limit', -1); |
|
193 | |||
194 | // this code cannot be tested because we cannot control the system settings in unit tests |
||
195 | // @codeCoverageIgnoreStart |
||
196 | if (extension_loaded('Zend OPcache') && ini_get('opcache.enable') && ini_get('opcache.enable_cli')) { |
||
197 | if (ini_get('opcache.save_comments')) { |
||
198 | ini_set('opcache.load_comments', 1); |
||
199 | } else { |
||
200 | ini_set('opcache.enable', 0); |
||
201 | } |
||
202 | } |
||
203 | |||
204 | if (extension_loaded('Zend Optimizer+') && ini_get('zend_optimizerplus.save_comments') == 0) { |
||
205 | throw new \RuntimeException('Please enable zend_optimizerplus.save_comments in php.ini.'); |
||
206 | } |
||
207 | // @codeCoverageIgnoreEnd |
||
208 | 1 | } |
|
209 | |||
210 | /** |
||
211 | * If the timezone is not set anywhere, set it to UTC. |
||
212 | * |
||
213 | * This is done to prevent any warnings being outputted in relation to using |
||
214 | * date/time functions. What is checked is php.ini, and if the PHP version |
||
215 | * is prior to 5.4, the TZ environment variable. |
||
216 | * |
||
217 | * @link http://php.net/manual/en/function.date-default-timezone-get.php for more information how PHP determines the |
||
218 | * default timezone. |
||
219 | * |
||
220 | * @codeCoverageIgnore this method is very hard, if not impossible, to unit test and not critical. |
||
221 | * |
||
222 | * @return void |
||
223 | */ |
||
224 | protected function setTimezone() |
||
225 | { |
||
226 | if (false == ini_get('date.timezone') |
||
227 | || (version_compare(phpversion(), '5.4.0', '<') && false === getenv('TZ')) |
||
228 | ) { |
||
229 | date_default_timezone_set('UTC'); |
||
230 | } |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Adds a logging provider to the container of phpDocumentor. |
||
235 | * |
||
236 | * @return void |
||
237 | */ |
||
238 | protected function addLogging() |
||
239 | { |
||
240 | $this->register( |
||
241 | new MonologServiceProvider(), |
||
242 | array( |
||
243 | 'monolog.name' => 'phpDocumentor', |
||
244 | 'monolog.logfile' => sys_get_temp_dir() . '/phpdoc.log', |
||
245 | 'monolog.debugfile' => sys_get_temp_dir() . '/phpdoc.debug.log', |
||
246 | 'monolog.level' => Logger::INFO, |
||
247 | ) |
||
248 | ); |
||
249 | |||
250 | $app = $this; |
||
251 | /** @var Configuration $configuration */ |
||
252 | $configuration = $this['config']; |
||
253 | $this['monolog.configure'] = $this->protect( |
||
254 | function ($log) use ($app, $configuration) { |
||
255 | $paths = $configuration->getLogging()->getPaths(); |
||
256 | $logLevel = $configuration->getLogging()->getLevel(); |
||
257 | |||
258 | $app->configureLogger($log, $logLevel, $paths['default'], $paths['errors']); |
||
0 ignored issues
–
show
|
|||
259 | } |
||
260 | ); |
||
261 | |||
262 | $this->extend( |
||
263 | 'console', |
||
264 | function (ConsoleApplication $console) use ($configuration) { |
||
265 | $console->getHelperSet()->set(new LoggerHelper()); |
||
266 | $console->getHelperSet()->set(new ConfigurationHelper($configuration)); |
||
267 | |||
268 | return $console; |
||
269 | } |
||
270 | ); |
||
271 | |||
272 | ErrorHandler::register($this['monolog']); |
||
273 | } |
||
274 | |||
275 | /** |
||
276 | * Adds the event dispatcher to phpDocumentor's container. |
||
277 | * |
||
278 | * @return void |
||
279 | */ |
||
280 | protected function addEventDispatcher() |
||
281 | { |
||
282 | 1 | $this['event_dispatcher'] = function () { |
|
283 | 1 | return Event\Dispatcher::getInstance(); |
|
284 | }; |
||
285 | 1 | } |
|
286 | |||
287 | /** |
||
288 | * Adds the command to phpDocumentor that belong to the Project namespace. |
||
289 | * |
||
290 | * @return void |
||
291 | */ |
||
292 | 1 | protected function addCommandsForProjectNamespace() |
|
293 | { |
||
294 | 1 | $this->command(new Command\Project\RunCommand()); |
|
295 | 1 | } |
|
296 | |||
297 | /** |
||
298 | * Adds the command to phpDocumentor that belong to the Phar namespace. |
||
299 | * |
||
300 | * @return void |
||
301 | */ |
||
302 | protected function addCommandsForPharNamespace() |
||
303 | { |
||
304 | $this->command(new Command\Phar\UpdateCommand()); |
||
305 | } |
||
306 | } |
||
307 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.