source: spip-zone/_outils_/spip-cli/trunk/src/Application.php @ 112581

Last change on this file since 112581 was 112581, checked in by cedric@…, 2 years ago

synchroniser spip-cli sur la date systeme si pas configuree dans le php.ini, c'est mieux que le UTC par defaut

File size: 6.7 KB
Line 
1<?php
2
3namespace Spip\Cli;
4
5use Psr\Container\ContainerInterface;
6use Simplex\Container;
7use Spip\Cli\Console\Style\SpipCliStyle;
8use Symfony\Component\Console\Application as ConsoleApplication;
9use Symfony\Component\Console\Input\ArgvInput;
10use Symfony\Component\Console\Input\ArrayInput;
11use Symfony\Component\Finder\Finder;
12use Symfony\Component\Console\Input\InputInterface;
13use Symfony\Component\Console\Output\ConsoleOutput;
14use Symfony\Component\Console\Output\OutputInterface;
15
16class Application extends ConsoleApplication {
17
18        const NAME = "Spip Cli";
19        const VERSION = "0.5.4";
20
21        /** @var Container */
22        protected $container;
23
24        /**
25         * Application constructor.
26         *
27         * Charge automatiquement les commandes présentes
28         * dans le répertoire Command de ce projet.
29         *
30         * @param array $options
31         */
32        public function __construct(array $options = []) {
33                parent::__construct(self::NAME, self::VERSION);
34
35                $this->container = new Container([], $options + [
36                        'debug' => false,
37                        'spip.directory' => null,
38                        'spip.webmestre.email' => '',
39                        'spip.webmestre.login' => '',
40                        'spip.webmestre.nom' => '',
41                        'spip.webmestre.login.prefixe' => 'SpipCli-',
42                        'cwd' => getcwd()
43                ]);
44
45                $this->setTimezone();
46                $this->registerServices();
47                $this->registerCommandsInProject(/*self::class*/ __CLASS__);
48                $this->loadSpip(); // hum…
49                $this->registerCommandsInSpip();
50        }
51
52
53        protected function registerServices() {
54                $app = $this;
55                $container = $this->container;
56                $container->set('console.io', function() use ($app) {
57                        return function(InputInterface $input = null, OutputInterface $output = null) use ($app) {
58                                if (null === $input) {
59                                        $input = new ArgvInput();
60                                }
61                                if (null === $output) {
62                                        $output = new ConsoleOutput();
63                                        $app->configureIO($input, $output);
64                                }
65                                return new Console\Style\SpipCliStyle($input, $output);
66                        };
67                });
68                $container->set('loader.spip', function (ContainerInterface $container) {
69                        $spip = new Loader\Spip($container->get('spip.directory'));
70                        $spip->setContainer($container);
71                        return $spip;
72                });
73                $container->set('sql.query', function (ContainerInterface $container) {
74                        $connect = $container->get('loader.spip')->getPathConnect();
75                        if (!is_file($connect)) {
76                                throw new \Exception('SPIP database is not configured');
77                        }
78                        $sql = new Loader\Sql($connect);
79                        return new Sql\Query($sql);
80                });
81        }
82
83        /**
84         * @note
85         * Alors ça, il faudrait plutôt que ça soit les commandes
86         * qui demandent le chargement de SPIP si elles en ont besoin,
87         * afin de faire des commandes où SPIP n’est pas chargé encore…
88         */
89        public function loadSpip() {
90                try {
91                        $spip = $this->container->get('loader.spip');
92                        $spip->load();
93                } catch (\Exception $e) {
94                        $io = $this->getIo();
95                        if (!in_array($io->getVerbosity(), [
96                                OutputInterface::VERBOSITY_QUIET,
97                                OutputInterface::VERBOSITY_NORMAL
98                        ])) {
99                                $io->note($e->getMessage());
100                        }
101                }
102        }
103
104
105        /**
106         * Ajoute les commandes contenues dans le répertoire Command du même chemin que la classe transmise
107         */
108        public function registerCommandsInProject($class) {
109                foreach ($this->findCommandsInProject($class) as $command) {
110                        if (class_exists($command)) {
111                                $this->add(new $command());
112                        }
113                }
114        }
115
116        /**
117         * Retourne la liste des commandes au même niveau que ce projet
118         * @return array
119         * @throws \ReflectionException
120         */
121        public function findCommandsInProject($class) {
122                $class = new \ReflectionClass($class);
123                $commandDir = dirname($class->getFilename()) . '/Command'; // .../spip-cli/src/Command
124                $list = [];
125                if (is_dir($commandDir)) {
126                        $namespace = $class->getNamespaceName(); // Spip\Cli
127                        $finder = new Finder();
128                        $finder->files()->in($commandDir)->name('*.php');
129                        foreach ($finder as $file) {
130                                // Spip\Cli\Command\Name
131                                $list[] = $namespace . '\\Command\\' . str_replace('/', '\\', substr($file->getRelativePathname(), 0, -4));
132                        }
133                }
134                return $list;
135        }
136
137        /**
138         * Chargement automatique des commandes spip-cli/ présentes dans les répertoires spip-cli/
139         * des plugins SPIP
140         */
141        public function registerCommandsInSpip() {
142                // les commandes dans spip-cli/ des plugins SPIP actifs
143                $this->registerSpipCliPluginsCommands();
144                // charger les vilaines globales utilisées dans les commandes spip-cli
145                try {
146                        global $spip_racine, $spip_loaded, $cwd;
147                        $cwd = getcwd();
148                        $spip = $this->container->get('loader.spip');
149                        $spip_racine = $spip->getDirectory();
150                        $spip_loaded = $spip->load();
151                } catch (\Exception $e) {
152                        return false;
153                }
154        }
155
156        /**
157         * Chargement des commandes présentes dans 'spip-cli/' des plugins SPIP actifs.
158         *
159         * Nécessite de démarrer SPIP (et donc d’être dans un SPIP)
160         * @return bool
161         */
162        public function registerSpipCliPluginsCommands() {
163                try {
164                        $spip = $this->container->get('loader.spip');
165                        if (!$spip->load()) {
166                                return false;
167                        }
168                } catch (\Exception $e) {
169                        return false;
170                }
171                $cwd = getcwd();
172                $spip->chdir();
173                $commandes = find_all_in_path('spip-cli/', '.*[.]php$');
174                foreach ($commandes as $path) {
175                        $this->registerSpipCliCommand($path);
176                }
177                chdir($cwd);
178        }
179
180        /**
181         * Déclare une commande "Spip Cli"
182         * @return bool
183         */
184        public function registerSpipCliCommand($path) {
185                include_once($path);
186                $command = '\\' . basename($path, '.php');
187                if ($namespace = Tools\Files::getNamespace($path)) {
188                        $command = '\\' . $namespace . $command;
189                }
190                if (class_exists($command)) {
191                        $this->add(new $command());
192                }
193        }
194
195        /**
196         * If the timezone is not set anywhere, set it to UTC.
197         * @return void
198         */
199        protected function setTimezone() {
200                if (false == ini_get('date.timezone')) {
201                        // on se synchro sur la date system si possible
202                        $date = trim(shell_exec("date -R"));
203                        $date = explode(' ', $date);
204                        if (preg_match(",^[+-][0-9][0-9][0-9][0-9]$,", end($date))
205                          and $zone = timezone_name_from_abbr("", 3600 * intval(end($date))/100, 0)) {
206                                date_default_timezone_set($zone);
207                        }
208                        else {
209                                date_default_timezone_set('UTC');
210                        }
211                }
212        }
213
214        public function getContainer() {
215                return $this->container;
216        }
217
218        public function getService($name) {
219                return $this->container->get($name);
220        }
221
222        /**
223         * @param InputInterface|null $input
224         * @param OutputInterface|null $output
225         * @return SpipCliStyle
226         */
227        public function getIo(InputInterface $input = null, OutputInterface $output = null) {
228                $io = $this->container->get('console.io');
229                return $io($input, $output);
230        }
231
232
233        /**
234         * Affiche l’aide d’une commande donnée
235         * @param string $commandName
236         * @param OutputInterface|null $output
237         */
238        public function showHelp($commandName, OutputInterface $output = null) {
239                if (null === $output) {
240                        $output = new ConsoleOutput();
241                }
242                $command = $this->find('help');
243                $arguments = array(
244                        'command' => 'help',
245                        'command_name' => $commandName,
246                );
247                $input = new ArrayInput($arguments);
248                $command->run($input, $output);
249        }
250}
Note: See TracBrowser for help on using the repository browser.