xref: /plugin/combo/cli.php (revision 82a60d039cd81033dc8147c27f0a50716b7a5301)
1007225e5Sgerardnico<?php
2007225e5Sgerardnico/**
3007225e5Sgerardnico * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved.
4007225e5Sgerardnico *
5007225e5Sgerardnico * This source code is licensed under the GPL license found in the
6007225e5Sgerardnico * COPYING  file in the root directory of this source tree.
7007225e5Sgerardnico *
8007225e5Sgerardnico * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
9007225e5Sgerardnico * @author   ComboStrap <support@combostrap.com>
10007225e5Sgerardnico *
11007225e5Sgerardnico */
12007225e5Sgerardnicoif (!defined('DOKU_INC')) die();
13007225e5Sgerardnico
14c3437056SNickeauuse ComboStrap\AnalyticsDocument;
15c3437056SNickeauuse ComboStrap\BacklinkCount;
16c3437056SNickeauuse ComboStrap\Event;
17c3437056SNickeauuse ComboStrap\ExceptionCombo;
18c3437056SNickeauuse ComboStrap\ExceptionComboRuntime;
1937748cd8SNickeauuse ComboStrap\FsWikiUtility;
20c3437056SNickeauuse ComboStrap\LogUtility;
21c3437056SNickeauuse ComboStrap\MetadataFrontmatterStore;
2271f916b9Sgerardnicouse ComboStrap\Page;
23c3437056SNickeauuse ComboStrap\PageH1;
2471f916b9Sgerardnicouse ComboStrap\Sqlite;
25007225e5Sgerardnicouse splitbrain\phpcli\Options;
26007225e5Sgerardnico
27e8b2ff59SNickeau/**
28e8b2ff59SNickeau * All dependency are loaded in plugin utility
29e8b2ff59SNickeau */
3037748cd8SNickeaurequire_once(__DIR__ . '/ComboStrap/PluginUtility.php');
31007225e5Sgerardnico
32007225e5Sgerardnico/**
33007225e5Sgerardnico * The memory of the server 128 is not enough
34007225e5Sgerardnico */
35007225e5Sgerardnicoini_set('memory_limit', '256M');
36007225e5Sgerardnico
37c3437056SNickeau
38007225e5Sgerardnico/**
39007225e5Sgerardnico * Class cli_plugin_combo
40007225e5Sgerardnico *
41007225e5Sgerardnico * This is a cli:
42007225e5Sgerardnico * https://www.dokuwiki.org/devel:cli_plugins#example
43007225e5Sgerardnico *
44007225e5Sgerardnico * Usage:
45007225e5Sgerardnico *
46007225e5Sgerardnico * ```
47007225e5Sgerardnico * docker exec -ti $(CONTAINER) /bin/bash
48c3437056SNickeau * ```
49c3437056SNickeau * ```
50c3437056SNickeau * set animal=animal-directory-name
51c3437056SNickeau * php ./bin/plugin.php combo --help
52007225e5Sgerardnico * ```
53007225e5Sgerardnico * or via the IDE
54007225e5Sgerardnico *
55007225e5Sgerardnico *
56007225e5Sgerardnico * Example:
57007225e5Sgerardnico * https://www.dokuwiki.org/tips:grapher
58007225e5Sgerardnico *
59007225e5Sgerardnico */
60007225e5Sgerardnicoclass cli_plugin_combo extends DokuWiki_CLI_Plugin
61007225e5Sgerardnico{
62c3437056SNickeau
63c3437056SNickeau    const METADATA_TO_DATABASE = "metadata-to-database";
6471f916b9Sgerardnico    const ANALYTICS = "analytics";
65c3437056SNickeau    const METADATA_TO_FRONTMATTER = "metadata-to-frontmatter";
6671f916b9Sgerardnico    const SYNC = "sync";
67c3437056SNickeau    const PLUGINS_TO_UPDATE = "plugins-to-update";
68c3437056SNickeau    const FORCE_OPTION = 'force';
69c3437056SNickeau    const PORT_OPTION = 'port';
70c3437056SNickeau    const HOST_OPTION = 'host';
71c3437056SNickeau
72007225e5Sgerardnico
73007225e5Sgerardnico    /**
74007225e5Sgerardnico     * register options and arguments
75007225e5Sgerardnico     * @param Options $options
76*82a60d03SNickeau     *
77*82a60d03SNickeau     * Note the animal is set in {@link DokuWikiFarmCore::detectAnimal()}
78*82a60d03SNickeau     * via the environment variable `animal` that is passed in the $_SERVER variable
79007225e5Sgerardnico     */
80007225e5Sgerardnico    protected function setup(Options $options)
81007225e5Sgerardnico    {
82c3437056SNickeau        $help = <<<EOF
83c3437056SNickeauComboStrap Administrative Commands
84c3437056SNickeau
85c3437056SNickeau
86c3437056SNickeauExample:
87c3437056SNickeau  * Replicate all pages into the database
88c3437056SNickeau```bash
89c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database :
90c3437056SNickeau# or
91c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database /
92c3437056SNickeau```
93c3437056SNickeau  * Replicate only the page `:namespace:my-page`
94c3437056SNickeau```bash
95c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database :namespace:my-page
96c3437056SNickeau# or
97c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database /namespace/my-page
98c3437056SNickeau```
99c3437056SNickeau
100c3437056SNickeauAnimal: If you want to use it for an animal farm, you need to set first the animal directory name in a environment variable
101c3437056SNickeau```bash
102c3437056SNickeauset animal=animal-directory-name
103c3437056SNickeau```
104c3437056SNickeau
105c3437056SNickeauEOF;
106c3437056SNickeau
107c3437056SNickeau        $options->setHelp($help);
108007225e5Sgerardnico        $options->registerOption('version', 'print version', 'v');
109c3437056SNickeau        $options->registerCommand(self::METADATA_TO_DATABASE, "Replicate the file system metadata into the database");
110c3437056SNickeau        $options->registerCommand(self::ANALYTICS, "Start the analytics and export optionally the data");
111c3437056SNickeau        $options->registerCommand(self::PLUGINS_TO_UPDATE, "List the plugins to update");
112c3437056SNickeau        $options->registerCommand(self::METADATA_TO_FRONTMATTER, "Replicate the file system metadata into the page frontmatter");
113c3437056SNickeau        $options->registerCommand(self::SYNC, "Delete the non-existing pages in the database");
114c3437056SNickeau        $options->registerArgument(
115c3437056SNickeau            'path',
116c3437056SNickeau            "The start path (a page or a directory). For all pages, type the root directory '/'",
117c3437056SNickeau            false
11871f916b9Sgerardnico        );
119007225e5Sgerardnico        $options->registerOption(
120007225e5Sgerardnico            'output',
121007225e5Sgerardnico            "Optional, where to store the analytical data as csv eg. a filename.",
122c3437056SNickeau            'o',
123c3437056SNickeau            true
124c3437056SNickeau        );
125007225e5Sgerardnico        $options->registerOption(
126c3437056SNickeau            self::HOST_OPTION,
127c3437056SNickeau            "The http host name of your server. This value is used by dokuwiki in the rendering cache key",
128c3437056SNickeau            null,
129c3437056SNickeau            true,
130c3437056SNickeau            self::METADATA_TO_DATABASE
131c3437056SNickeau        );
132c3437056SNickeau        $options->registerOption(
133c3437056SNickeau            self::PORT_OPTION,
134c3437056SNickeau            "The http host port of your server. This value is used by dokuwiki in the rendering cache key",
135c3437056SNickeau            null,
136c3437056SNickeau            true,
137c3437056SNickeau            self::METADATA_TO_DATABASE
138c3437056SNickeau        );
139c3437056SNickeau        $options->registerOption(
140c3437056SNickeau            self::FORCE_OPTION,
141c3437056SNickeau            "Replicate with force",
142c3437056SNickeau            'f',
143c3437056SNickeau            false,
144c3437056SNickeau            self::METADATA_TO_DATABASE
145c3437056SNickeau        );
14671f916b9Sgerardnico        $options->registerOption(
14771f916b9Sgerardnico            'dry',
14871f916b9Sgerardnico            "Optional, dry-run",
14971f916b9Sgerardnico            'd', false);
150c3437056SNickeau
151007225e5Sgerardnico
152007225e5Sgerardnico    }
153007225e5Sgerardnico
154007225e5Sgerardnico    /**
155007225e5Sgerardnico     * The main entry
156007225e5Sgerardnico     * @param Options $options
157*82a60d03SNickeau     * @throws ExceptionCombo
158007225e5Sgerardnico     */
159007225e5Sgerardnico    protected function main(Options $options)
160007225e5Sgerardnico    {
161007225e5Sgerardnico
162007225e5Sgerardnico
163*82a60d03SNickeau        if(isset($_REQUEST['animal'])){
164*82a60d03SNickeau            echo "Animal detected: ".$_REQUEST['animal']."\n";
165*82a60d03SNickeau        } else {
166*82a60d03SNickeau            echo "No Animal detected\n";
167*82a60d03SNickeau            echo "Conf: ".DOKU_CONF."\n";
168*82a60d03SNickeau        }
169*82a60d03SNickeau
170c3437056SNickeau        $args = $options->getArgs();
171c3437056SNickeau
172c3437056SNickeau
17371f916b9Sgerardnico        $depth = $options->getOpt('depth', 0);
17421913ab3SNickeau        $cmd = $options->getCmd();
17521913ab3SNickeau        switch ($cmd) {
176c3437056SNickeau            case self::METADATA_TO_DATABASE:
177c3437056SNickeau                $startPath = $this->getStartPath($args);
178c3437056SNickeau                $force = $options->getOpt(self::FORCE_OPTION, false);
179c3437056SNickeau                $hostOptionValue = $options->getOpt(self::HOST_OPTION, null);
180c3437056SNickeau                if ($hostOptionValue === null) {
181c3437056SNickeau                    fwrite(STDERR, "The host name is mandatory");
182c3437056SNickeau                    return;
183c3437056SNickeau                }
184c3437056SNickeau                $_SERVER['HTTP_HOST'] = $hostOptionValue;
185c3437056SNickeau                $portOptionName = $options->getOpt(self::PORT_OPTION, null);
186c3437056SNickeau                if ($portOptionName === null) {
187c3437056SNickeau                    fwrite(STDERR, "The host port is mandatory");
188c3437056SNickeau                    return;
189c3437056SNickeau                }
190c3437056SNickeau                $_SERVER['SERVER_PORT'] = $portOptionName;
191c3437056SNickeau                $this->index($startPath, $force, $depth);
192c3437056SNickeau                break;
193c3437056SNickeau            case self::METADATA_TO_FRONTMATTER:
194c3437056SNickeau                $startPath = $this->getStartPath($args);
195c3437056SNickeau                $this->frontmatter($startPath, $depth);
196c3437056SNickeau                break;
19771f916b9Sgerardnico            case self::ANALYTICS:
198c3437056SNickeau                $startPath = $this->getStartPath($args);
199007225e5Sgerardnico                $output = $options->getOpt('output', '');
200007225e5Sgerardnico                //if ($output == '-') $output = 'php://stdout';
201c3437056SNickeau                $this->analytics($startPath, $output, $depth);
20271f916b9Sgerardnico                break;
20371f916b9Sgerardnico            case self::SYNC:
204c3437056SNickeau                $this->deleteNonExistingPageFromDatabase();
205c3437056SNickeau                break;
206c3437056SNickeau            case self::PLUGINS_TO_UPDATE:
207c3437056SNickeau                /**
208c3437056SNickeau                 * Endpoint:
209c3437056SNickeau                 * self::EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name)
210c3437056SNickeau                 * `http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php?fmt=php&ext[]=`.urlencode($name)
211c3437056SNickeau                 */
212c3437056SNickeau                $pluginList = plugin_list('', true);
213c3437056SNickeau                /* @var helper_plugin_extension_extension $extension */
214c3437056SNickeau                $extension = $this->loadHelper('extension_extension');
215c3437056SNickeau                foreach ($pluginList as $name) {
216c3437056SNickeau                    $extension->setExtension($name);
217c3437056SNickeau                    if ($extension->updateAvailable()) {
218c3437056SNickeau                        echo "The extension $name should be updated";
219c3437056SNickeau                    }
220c3437056SNickeau                }
22171f916b9Sgerardnico                break;
22271f916b9Sgerardnico            default:
223c3437056SNickeau                if ($cmd !== "") {
224c3437056SNickeau                    fwrite(STDERR, "Combo: Command unknown (" . $cmd . ")");
225c3437056SNickeau                } else {
226c3437056SNickeau                    echo $options->help();
227c3437056SNickeau                }
228c3437056SNickeau                exit(1);
22971f916b9Sgerardnico        }
230007225e5Sgerardnico
231007225e5Sgerardnico
232007225e5Sgerardnico    }
233007225e5Sgerardnico
234007225e5Sgerardnico    /**
23571f916b9Sgerardnico     * @param array $namespaces
236c3437056SNickeau     * @param bool $rebuild
237007225e5Sgerardnico     * @param int $depth recursion depth. 0 for unlimited
238c3437056SNickeau     * @throws ExceptionCombo
239007225e5Sgerardnico     */
240c3437056SNickeau    private function index($namespaces = array(), $rebuild = false, $depth = 0)
241c3437056SNickeau    {
242c3437056SNickeau
243c3437056SNickeau        /**
244c3437056SNickeau         * Run as admin to overcome the fact that
245c3437056SNickeau         * anonymous user cannot see all links and backlinks
246c3437056SNickeau         */
247c3437056SNickeau        global $USERINFO;
248c3437056SNickeau        $USERINFO['grps'] = array('admin');
249c3437056SNickeau        global $INPUT;
250c3437056SNickeau        $INPUT->server->set('REMOTE_USER', "cli");
251c3437056SNickeau
252c3437056SNickeau        $pages = FsWikiUtility::getPages($namespaces, $depth);
253c3437056SNickeau
254c3437056SNickeau        $pageCounter = 0;
255c3437056SNickeau        $totalNumberOfPages = sizeof($pages);
256c3437056SNickeau        while ($pageArray = array_shift($pages)) {
257c3437056SNickeau            $id = $pageArray['id'];
258c3437056SNickeau            /**
259c3437056SNickeau             * Indexing the page start the database replication
260c3437056SNickeau             * See {@link action_plugin_combo_fulldatabasereplication}
261c3437056SNickeau             */
262c3437056SNickeau            $pageCounter++;
263c3437056SNickeau            try {
264c3437056SNickeau                /**
265c3437056SNickeau                 * If the page does not need to be indexed, there is no run
266c3437056SNickeau                 * and false is returned
267c3437056SNickeau                 */
268c3437056SNickeau                $indexedOrNot = idx_addPage($id, true, true);
269c3437056SNickeau                if ($indexedOrNot) {
270c3437056SNickeau                    LogUtility::msg("The page {$id} ($pageCounter / $totalNumberOfPages) was indexed and replicated", LogUtility::LVL_MSG_INFO);
271c3437056SNickeau                } else {
272c3437056SNickeau                    LogUtility::msg("The page {$id} ($pageCounter / $totalNumberOfPages) has an error", LogUtility::LVL_MSG_ERROR);
273c3437056SNickeau                }
274c3437056SNickeau            } catch (ExceptionComboRuntime $e) {
275c3437056SNickeau                LogUtility::msg("The page {$id} ($pageCounter / $totalNumberOfPages) has an error: " . $e->getMessage(), LogUtility::LVL_MSG_ERROR);
276c3437056SNickeau            }
277c3437056SNickeau        }
278c3437056SNickeau        /**
279c3437056SNickeau         * Process all backlinks
280c3437056SNickeau         */
281c3437056SNickeau        echo "Processing Replication Request\n";
282c3437056SNickeau        Event::dispatchEvent(PHP_INT_MAX);
283c3437056SNickeau
284c3437056SNickeau    }
285c3437056SNickeau
286c3437056SNickeau    private function analytics($namespaces = array(), $output = null, $depth = 0)
287007225e5Sgerardnico    {
288007225e5Sgerardnico
289007225e5Sgerardnico        $fileHandle = null;
290007225e5Sgerardnico        if (!empty($output)) {
291007225e5Sgerardnico            $fileHandle = @fopen($output, 'w');
292007225e5Sgerardnico            if (!$fileHandle) $this->fatal("Failed to open $output");
293007225e5Sgerardnico        }
294007225e5Sgerardnico
29537748cd8SNickeau        /**
29637748cd8SNickeau         * Run as admin to overcome the fact that
29737748cd8SNickeau         * anonymous user cannot see all links and backlinks
29837748cd8SNickeau         */
29937748cd8SNickeau        global $USERINFO;
30037748cd8SNickeau        $USERINFO['grps'] = array('admin');
30137748cd8SNickeau        global $INPUT;
30237748cd8SNickeau        $INPUT->server->set('REMOTE_USER', "cli");
30337748cd8SNickeau
30437748cd8SNickeau        $pages = FsWikiUtility::getPages($namespaces, $depth);
305007225e5Sgerardnico
306007225e5Sgerardnico
307007225e5Sgerardnico        if (!empty($fileHandle)) {
308007225e5Sgerardnico            $header = array(
309007225e5Sgerardnico                'id',
310007225e5Sgerardnico                'backlinks',
311007225e5Sgerardnico                'broken_links',
312007225e5Sgerardnico                'changes',
313007225e5Sgerardnico                'chars',
314007225e5Sgerardnico                'external_links',
315007225e5Sgerardnico                'external_medias',
316007225e5Sgerardnico                'h1',
317007225e5Sgerardnico                'h2',
318007225e5Sgerardnico                'h3',
319007225e5Sgerardnico                'h4',
320007225e5Sgerardnico                'h5',
321007225e5Sgerardnico                'internal_links',
322007225e5Sgerardnico                'internal_medias',
323007225e5Sgerardnico                'words',
324007225e5Sgerardnico                'score'
325007225e5Sgerardnico            );
326007225e5Sgerardnico            fwrite($fileHandle, implode(",", $header) . PHP_EOL);
327007225e5Sgerardnico        }
3289da76789Sgerardnico        $pageCounter = 0;
329e8b2ff59SNickeau        $totalNumberOfPages = sizeof($pages);
330c3437056SNickeau        while ($pageArray = array_shift($pages)) {
331c3437056SNickeau            $id = $pageArray['id'];
332c3437056SNickeau            $page = Page::createPageFromId($id);
333c3437056SNickeau
334007225e5Sgerardnico
3359da76789Sgerardnico            $pageCounter++;
336c3437056SNickeau            echo "Analytics Processing for the page {$id} ($pageCounter / $totalNumberOfPages)\n";
337007225e5Sgerardnico
338c3437056SNickeau            /**
339c3437056SNickeau             * Analytics
340c3437056SNickeau             */
341c3437056SNickeau            $analytics = $page->getAnalyticsDocument();
342c3437056SNickeau            $data = $analytics->getOrProcessContent()->toArray();
343c3437056SNickeau
344007225e5Sgerardnico            if (!empty($fileHandle)) {
345c3437056SNickeau                $statistics = $data[AnalyticsDocument::STATISTICS];
346007225e5Sgerardnico                $row = array(
347007225e5Sgerardnico                    'id' => $id,
348c3437056SNickeau                    'backlinks' => $statistics[BacklinkCount::getPersistentName()],
349c3437056SNickeau                    'broken_links' => $statistics[AnalyticsDocument::INTERNAL_LINK_BROKEN_COUNT],
350c3437056SNickeau                    'changes' => $statistics[AnalyticsDocument::EDITS_COUNT],
351c3437056SNickeau                    'chars' => $statistics[AnalyticsDocument::CHAR_COUNT],
352c3437056SNickeau                    'external_links' => $statistics[AnalyticsDocument::EXTERNAL_LINK_COUNT],
353c3437056SNickeau                    'external_medias' => $statistics[AnalyticsDocument::EXTERNAL_MEDIA_COUNT],
354c3437056SNickeau                    PageH1::PROPERTY_NAME => $statistics[AnalyticsDocument::HEADING_COUNT][PageH1::PROPERTY_NAME],
355c3437056SNickeau                    'h2' => $statistics[AnalyticsDocument::HEADING_COUNT]['h2'],
356c3437056SNickeau                    'h3' => $statistics[AnalyticsDocument::HEADING_COUNT]['h3'],
357c3437056SNickeau                    'h4' => $statistics[AnalyticsDocument::HEADING_COUNT]['h4'],
358c3437056SNickeau                    'h5' => $statistics[AnalyticsDocument::HEADING_COUNT]['h5'],
359c3437056SNickeau                    'internal_links' => $statistics[AnalyticsDocument::INTERNAL_LINK_COUNT],
360c3437056SNickeau                    'internal_medias' => $statistics[AnalyticsDocument::INTERNAL_MEDIA_COUNT],
361c3437056SNickeau                    'words' => $statistics[AnalyticsDocument::WORD_COUNT],
362c3437056SNickeau                    'low' => $data[AnalyticsDocument::QUALITY]['low']
363007225e5Sgerardnico                );
364007225e5Sgerardnico                fwrite($fileHandle, implode(",", $row) . PHP_EOL);
365007225e5Sgerardnico            }
366c3437056SNickeau
367007225e5Sgerardnico        }
368007225e5Sgerardnico        if (!empty($fileHandle)) {
369007225e5Sgerardnico            fclose($fileHandle);
370007225e5Sgerardnico        }
371007225e5Sgerardnico
372007225e5Sgerardnico    }
37371f916b9Sgerardnico
374325fe0c5Sgerardnico
375c3437056SNickeau    private function deleteNonExistingPageFromDatabase()
37671f916b9Sgerardnico    {
377c3437056SNickeau        LogUtility::msg("Starting: Deleting non-existing page from database");
378c3437056SNickeau        $sqlite = Sqlite::createOrGetSqlite();
379c3437056SNickeau        $request = $sqlite
380c3437056SNickeau            ->createRequest()
381c3437056SNickeau            ->setQuery("select id as \"id\" from pages");
382c3437056SNickeau        $rows = [];
383c3437056SNickeau        try {
384c3437056SNickeau            $rows = $request
385c3437056SNickeau                ->execute()
386c3437056SNickeau                ->getRows();
387c3437056SNickeau        } catch (ExceptionCombo $e) {
388c3437056SNickeau            LogUtility::msg("Error while getting the id pages. {$e->getMessage()}");
389c3437056SNickeau            return;
390c3437056SNickeau        } finally {
391c3437056SNickeau            $request->close();
39271f916b9Sgerardnico        }
393c3437056SNickeau        $counter = 0;
394c3437056SNickeau        foreach ($rows as $row) {
395c3437056SNickeau            $counter++;
396c3437056SNickeau            $id = $row['id'];
39771f916b9Sgerardnico            if (!page_exists($id)) {
39871f916b9Sgerardnico                echo 'Page does not exist on the file system. Deleted from the database (' . $id . ")\n";
399c3437056SNickeau                Page::createPageFromId($id)->getDatabasePage()->delete();
400c3437056SNickeau            }
401c3437056SNickeau        }
402c3437056SNickeau        LogUtility::msg("Sync finished ($counter pages checked)");
403c3437056SNickeau
404c3437056SNickeau
405c3437056SNickeau    }
406c3437056SNickeau
407c3437056SNickeau    private function frontmatter($namespaces, $depth)
408c3437056SNickeau    {
409c3437056SNickeau        $pages = FsWikiUtility::getPages($namespaces, $depth);
410c3437056SNickeau        $pageCounter = 0;
411c3437056SNickeau        $totalNumberOfPages = sizeof($pages);
412c3437056SNickeau        $pagesWithChanges = [];
413c3437056SNickeau        $pagesWithError = [];
414c3437056SNickeau        $pagesWithOthers = [];
415c3437056SNickeau        $notChangedCounter = 0;
416c3437056SNickeau        while ($pageArray = array_shift($pages)) {
417c3437056SNickeau            $id = $pageArray['id'];
418c3437056SNickeau            $page = Page::createPageFromId($id);
419c3437056SNickeau            $pageCounter++;
420c3437056SNickeau            LogUtility::msg("Processing page {$id} ($pageCounter / $totalNumberOfPages) ", LogUtility::LVL_MSG_INFO);
421c3437056SNickeau            try {
422c3437056SNickeau                $message = MetadataFrontmatterStore::createFromPage($page)
423c3437056SNickeau                    ->sync();
424c3437056SNickeau                switch ($message->getStatus()) {
425c3437056SNickeau                    case syntax_plugin_combo_frontmatter::UPDATE_EXIT_CODE_NOT_CHANGED:
426c3437056SNickeau                        $notChangedCounter++;
427c3437056SNickeau                        break;
428c3437056SNickeau                    case syntax_plugin_combo_frontmatter::UPDATE_EXIT_CODE_DONE:
429c3437056SNickeau                        $pagesWithChanges[] = $id;
430c3437056SNickeau                        break;
431c3437056SNickeau                    case syntax_plugin_combo_frontmatter::UPDATE_EXIT_CODE_ERROR:
432c3437056SNickeau                        $pagesWithError[$id] = $message->getPlainTextContent();
433c3437056SNickeau                        break;
434c3437056SNickeau                    default:
435c3437056SNickeau                        $pagesWithOthers[$id] = $message->getPlainTextContent();
436c3437056SNickeau                        break;
437c3437056SNickeau
438c3437056SNickeau                }
439c3437056SNickeau            } catch (ExceptionCombo $e) {
440c3437056SNickeau                $pagesWithError[$id] = $e->getMessage();
441c3437056SNickeau            }
442c3437056SNickeau
443c3437056SNickeau        }
444c3437056SNickeau
445c3437056SNickeau        echo "\n";
446c3437056SNickeau        echo "Result:\n";
447c3437056SNickeau        echo "$notChangedCounter pages without any frontmatter modifications\n";
448c3437056SNickeau
449c3437056SNickeau        if (sizeof($pagesWithError) > 0) {
450c3437056SNickeau            echo "\n";
451c3437056SNickeau            echo "The following pages had errors\n";
452c3437056SNickeau            $pageCounter = 0;
453c3437056SNickeau            $totalNumberOfPages = sizeof($pagesWithError);
454c3437056SNickeau            foreach ($pagesWithError as $id => $message) {
455c3437056SNickeau                $pageCounter++;
456c3437056SNickeau                LogUtility::msg("Page {$id} ($pageCounter / $totalNumberOfPages): " . $message, LogUtility::LVL_MSG_ERROR);
457c3437056SNickeau            }
458c3437056SNickeau        } else {
459c3437056SNickeau            echo "No error\n";
460c3437056SNickeau        }
461c3437056SNickeau
462c3437056SNickeau        if (sizeof($pagesWithChanges) > 0) {
463c3437056SNickeau            echo "\n";
464c3437056SNickeau            echo "The following pages had changed:\n";
465c3437056SNickeau            $pageCounter = 0;
466c3437056SNickeau            $totalNumberOfPages = sizeof($pagesWithChanges);
467c3437056SNickeau            foreach ($pagesWithChanges as $id) {
468c3437056SNickeau                $pageCounter++;
469c3437056SNickeau                LogUtility::msg("Page {$id} ($pageCounter / $totalNumberOfPages) ", LogUtility::LVL_MSG_ERROR);
470c3437056SNickeau            }
471c3437056SNickeau        } else {
472c3437056SNickeau            echo "No changes\n";
473c3437056SNickeau        }
474c3437056SNickeau
475c3437056SNickeau        if (sizeof($pagesWithOthers) > 0) {
476c3437056SNickeau            echo "\n";
477c3437056SNickeau            echo "The following pages had an other status";
478c3437056SNickeau            $pageCounter = 0;
479c3437056SNickeau            $totalNumberOfPages = sizeof($pagesWithOthers);
480c3437056SNickeau            foreach ($pagesWithOthers as $id => $message) {
481c3437056SNickeau                $pageCounter++;
482c3437056SNickeau                LogUtility::msg("Page {$id} ($pageCounter / $totalNumberOfPages) " . $message, LogUtility::LVL_MSG_ERROR);
483c3437056SNickeau            }
48471f916b9Sgerardnico        }
48571f916b9Sgerardnico    }
48671f916b9Sgerardnico
487c3437056SNickeau    private function getStartPath($args)
488c3437056SNickeau    {
489c3437056SNickeau        $sizeof = sizeof($args);
490c3437056SNickeau        switch ($sizeof) {
491c3437056SNickeau            case 0:
492c3437056SNickeau                fwrite(STDERR, "The start path is mandatory and was not given");
493c3437056SNickeau                exit(1);
494c3437056SNickeau            case 1:
495c3437056SNickeau                $startPath = $args[0];
496c3437056SNickeau                if (!in_array($startPath, [":", "/"])) {
497c3437056SNickeau                    // cleanId would return blank for a root
498c3437056SNickeau                    $startPath = cleanID($startPath);
499c3437056SNickeau                }
500c3437056SNickeau                break;
501c3437056SNickeau            default:
502c3437056SNickeau                fwrite(STDERR, "Too much arguments given $sizeof");
503c3437056SNickeau                exit(1);
504c3437056SNickeau        }
505c3437056SNickeau        return $startPath;
50671f916b9Sgerardnico    }
507007225e5Sgerardnico}
508