Update copyright
[friendica.git/.git] / src / Console / Typo.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Console;
23
24 use Friendica\Core\Config\IConfig;
25
26 /**
27  * Tired of chasing typos and finding them after a commit.
28  * Run this and quickly see if we've got any parse errors in our application files.
29  */
30 class Typo extends \Asika\SimpleConsole\Console
31 {
32         protected $helpOptions = ['h', 'help', '?'];
33
34         /**
35          * @var IConfig
36          */
37         private $config;
38
39         protected function getHelp()
40         {
41                 $help = <<<HELP
42 console typo - Checks for parse errors in Friendica files
43 Usage
44         bin/console typo [-h|--help|-?] [-v]
45
46 Description
47         Checks all PHP files in the Friendica file tree for parse errors
48
49 Options
50         -h|--help|-?  Show help information
51         -v            Show more debug information.
52 HELP;
53                 return $help;
54         }
55
56         public function __construct(IConfig $config, array $argv = null)
57         {
58                 parent::__construct($argv);
59
60                 $this->config = $config;
61         }
62
63         protected function doExecute()
64         {
65                 if ($this->getOption('v')) {
66                         $this->out('Class: ' . __CLASS__);
67                         $this->out('Arguments: ' . var_export($this->args, true));
68                         $this->out('Options: ' . var_export($this->options, true));
69                 }
70
71                 if (count($this->args) > 0) {
72                         throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
73                 }
74
75                 $php_path = $this->config->get('config', 'php_path', 'php');
76
77                 if ($this->getOption('v')) {
78                         $this->out('Directory: src');
79                 }
80
81                 $Iterator = new \RecursiveDirectoryIterator('src');
82
83                 foreach (new \RecursiveIteratorIterator($Iterator) as $file) {
84                         if (substr($file, -4) === '.php') {
85                                 $this->checkFile($php_path, $file);
86                         }
87                 }
88
89                 if ($this->getOption('v')) {
90                         $this->out('Directory: tests');
91                 }
92
93                 $Iterator = new \RecursiveDirectoryIterator('tests');
94
95                 foreach (new \RecursiveIteratorIterator($Iterator) as $file) {
96                         if (substr($file, -4) === '.php') {
97                                 $this->checkFile($php_path, $file);
98                         }
99                 }
100
101                 if ($this->getOption('v')) {
102                         $this->out('Directory: mod');
103                 }
104
105                 $files = glob('mod/*.php');
106                 $this->checkFiles($php_path, $files);
107
108                 if ($this->getOption('v')) {
109                         $this->out('Directory: include');
110                 }
111
112                 $files = glob('include/*.php');
113                 $this->checkFiles($php_path, $files);
114
115                 if ($this->getOption('v')) {
116                         $this->out('Directory: addon');
117                 }
118
119                 $dirs = glob('addon/*');
120                 foreach ($dirs as $dir) {
121                         $addon = basename($dir);
122                         $files = glob($dir . '/' . $addon . '.php');
123                         $this->checkFiles($php_path, $files);
124                 }
125
126                 if ($this->getOption('v')) {
127                         $this->out('String files');
128                 }
129
130                 $files = glob('view/lang/*/strings.php');
131                 $this->checkFiles($php_path, $files);
132
133                 $this->out('No errors.');
134
135                 return 0;
136         }
137
138         private function checkFiles($php_path, array $files)
139         {
140                 foreach ($files as $file) {
141                         $this->checkFile($php_path, $file);
142                 }
143         }
144
145         private function checkFile($php_path, $file)
146         {
147                 if ($this->getOption('v')) {
148                         $this->out('Checking ' . $file);
149                 }
150
151                 $output = [];
152                 $ret = 0;
153                 exec("$php_path -l $file", $output, $ret);
154                 if ($ret !== 0) {
155                         throw new \RuntimeException('Parse error found in ' . $file . ', scan stopped.');
156                 }
157         }
158 }