xref: /plugin/combo/cli.php (revision c3437056399326d621a01da73b649707fbb0ae69)
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
14*c3437056SNickeauuse ComboStrap\AnalyticsDocument;
15*c3437056SNickeauuse ComboStrap\BacklinkCount;
16*c3437056SNickeauuse ComboStrap\DatabasePageRow;
17*c3437056SNickeauuse ComboStrap\Event;
18*c3437056SNickeauuse ComboStrap\ExceptionCombo;
19*c3437056SNickeauuse ComboStrap\ExceptionComboRuntime;
2037748cd8SNickeauuse ComboStrap\FsWikiUtility;
21*c3437056SNickeauuse ComboStrap\LogUtility;
22*c3437056SNickeauuse ComboStrap\MetadataFrontmatterStore;
2371f916b9Sgerardnicouse ComboStrap\Page;
24*c3437056SNickeauuse ComboStrap\PageH1;
2571f916b9Sgerardnicouse ComboStrap\Sqlite;
26007225e5Sgerardnicouse splitbrain\phpcli\Options;
27007225e5Sgerardnico
28e8b2ff59SNickeau/**
29e8b2ff59SNickeau * All dependency are loaded in plugin utility
30e8b2ff59SNickeau */
3137748cd8SNickeaurequire_once(__DIR__ . '/ComboStrap/PluginUtility.php');
32007225e5Sgerardnico
33007225e5Sgerardnico/**
34007225e5Sgerardnico * The memory of the server 128 is not enough
35007225e5Sgerardnico */
36007225e5Sgerardnicoini_set('memory_limit', '256M');
37007225e5Sgerardnico
38*c3437056SNickeau
39007225e5Sgerardnico/**
40007225e5Sgerardnico * Class cli_plugin_combo
41007225e5Sgerardnico *
42007225e5Sgerardnico * This is a cli:
43007225e5Sgerardnico * https://www.dokuwiki.org/devel:cli_plugins#example
44007225e5Sgerardnico *
45007225e5Sgerardnico * Usage:
46007225e5Sgerardnico *
47007225e5Sgerardnico * ```
48007225e5Sgerardnico * docker exec -ti $(CONTAINER) /bin/bash
49*c3437056SNickeau * ```
50*c3437056SNickeau * ```
51*c3437056SNickeau * set animal=animal-directory-name
52*c3437056SNickeau * php ./bin/plugin.php combo --help
53007225e5Sgerardnico * ```
54007225e5Sgerardnico * or via the IDE
55007225e5Sgerardnico *
56007225e5Sgerardnico *
57007225e5Sgerardnico * Example:
58007225e5Sgerardnico * https://www.dokuwiki.org/tips:grapher
59007225e5Sgerardnico *
60007225e5Sgerardnico */
61007225e5Sgerardnicoclass cli_plugin_combo extends DokuWiki_CLI_Plugin
62007225e5Sgerardnico{
63*c3437056SNickeau
64*c3437056SNickeau    const METADATA_TO_DATABASE = "metadata-to-database";
6571f916b9Sgerardnico    const ANALYTICS = "analytics";
66*c3437056SNickeau    const METADATA_TO_FRONTMATTER = "metadata-to-frontmatter";
6771f916b9Sgerardnico    const SYNC = "sync";
68*c3437056SNickeau    const PLUGINS_TO_UPDATE = "plugins-to-update";
69*c3437056SNickeau    const FORCE_OPTION = 'force';
70*c3437056SNickeau    const PORT_OPTION = 'port';
71*c3437056SNickeau    const HOST_OPTION = 'host';
72*c3437056SNickeau
73007225e5Sgerardnico
74007225e5Sgerardnico    /**
75007225e5Sgerardnico     * register options and arguments
76007225e5Sgerardnico     * @param Options $options
77007225e5Sgerardnico     */
78007225e5Sgerardnico    protected function setup(Options $options)
79007225e5Sgerardnico    {
80*c3437056SNickeau        $help = <<<EOF
81*c3437056SNickeauComboStrap Administrative Commands
82*c3437056SNickeau
83*c3437056SNickeau
84*c3437056SNickeauExample:
85*c3437056SNickeau  * Replicate all pages into the database
86*c3437056SNickeau```bash
87*c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database :
88*c3437056SNickeau# or
89*c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database /
90*c3437056SNickeau```
91*c3437056SNickeau  * Replicate only the page `:namespace:my-page`
92*c3437056SNickeau```bash
93*c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database :namespace:my-page
94*c3437056SNickeau# or
95*c3437056SNickeauphp ./bin/plugin.php combo metadata-to-database /namespace/my-page
96*c3437056SNickeau```
97*c3437056SNickeau
98*c3437056SNickeauAnimal: If you want to use it for an animal farm, you need to set first the animal directory name in a environment variable
99*c3437056SNickeau```bash
100*c3437056SNickeauset animal=animal-directory-name
101*c3437056SNickeau```
102*c3437056SNickeau
103*c3437056SNickeauEOF;
104*c3437056SNickeau
105*c3437056SNickeau        $options->setHelp($help);
106007225e5Sgerardnico        $options->registerOption('version', 'print version', 'v');
107*c3437056SNickeau        $options->registerCommand(self::METADATA_TO_DATABASE, "Replicate the file system metadata into the database");
108*c3437056SNickeau        $options->registerCommand(self::ANALYTICS, "Start the analytics and export optionally the data");
109*c3437056SNickeau        $options->registerCommand(self::PLUGINS_TO_UPDATE, "List the plugins to update");
110*c3437056SNickeau        $options->registerCommand(self::METADATA_TO_FRONTMATTER, "Replicate the file system metadata into the page frontmatter");
111*c3437056SNickeau        $options->registerCommand(self::SYNC, "Delete the non-existing pages in the database");
112*c3437056SNickeau        $options->registerArgument(
113*c3437056SNickeau            'path',
114*c3437056SNickeau            "The start path (a page or a directory). For all pages, type the root directory '/'",
115*c3437056SNickeau            false
11671f916b9Sgerardnico        );
117007225e5Sgerardnico        $options->registerOption(
118007225e5Sgerardnico            'output',
119007225e5Sgerardnico            "Optional, where to store the analytical data as csv eg. a filename.",
120*c3437056SNickeau            'o',
121*c3437056SNickeau            true
122*c3437056SNickeau        );
123007225e5Sgerardnico        $options->registerOption(
124*c3437056SNickeau            self::HOST_OPTION,
125*c3437056SNickeau            "The http host name of your server. This value is used by dokuwiki in the rendering cache key",
126*c3437056SNickeau            null,
127*c3437056SNickeau            true,
128*c3437056SNickeau            self::METADATA_TO_DATABASE
129*c3437056SNickeau        );
130*c3437056SNickeau        $options->registerOption(
131*c3437056SNickeau            self::PORT_OPTION,
132*c3437056SNickeau            "The http host port of your server. This value is used by dokuwiki in the rendering cache key",
133*c3437056SNickeau            null,
134*c3437056SNickeau            true,
135*c3437056SNickeau            self::METADATA_TO_DATABASE
136*c3437056SNickeau        );
137*c3437056SNickeau        $options->registerOption(
138*c3437056SNickeau            self::FORCE_OPTION,
139*c3437056SNickeau            "Replicate with force",
140*c3437056SNickeau            'f',
141*c3437056SNickeau            false,
142*c3437056SNickeau            self::METADATA_TO_DATABASE
143*c3437056SNickeau        );
14471f916b9Sgerardnico        $options->registerOption(
14571f916b9Sgerardnico            'dry',
14671f916b9Sgerardnico            "Optional, dry-run",
14771f916b9Sgerardnico            'd', false);
148*c3437056SNickeau
149007225e5Sgerardnico
150007225e5Sgerardnico    }
151007225e5Sgerardnico
152007225e5Sgerardnico    /**
153007225e5Sgerardnico     * The main entry
154007225e5Sgerardnico     * @param Options $options
155007225e5Sgerardnico     */
156007225e5Sgerardnico    protected function main(Options $options)
157007225e5Sgerardnico    {
158007225e5Sgerardnico
159007225e5Sgerardnico
160*c3437056SNickeau        $args = $options->getArgs();
161*c3437056SNickeau
162*c3437056SNickeau
16371f916b9Sgerardnico        $depth = $options->getOpt('depth', 0);
16421913ab3SNickeau        $cmd = $options->getCmd();
16521913ab3SNickeau        switch ($cmd) {
166*c3437056SNickeau            case self::METADATA_TO_DATABASE:
167*c3437056SNickeau                $startPath = $this->getStartPath($args);
168*c3437056SNickeau                $force = $options->getOpt(self::FORCE_OPTION, false);
169*c3437056SNickeau                $hostOptionValue = $options->getOpt(self::HOST_OPTION, null);
170*c3437056SNickeau                if ($hostOptionValue === null) {
171*c3437056SNickeau                    fwrite(STDERR, "The host name is mandatory");
172*c3437056SNickeau                    return;
173*c3437056SNickeau                }
174*c3437056SNickeau                $_SERVER['HTTP_HOST'] = $hostOptionValue;
175*c3437056SNickeau                $portOptionName = $options->getOpt(self::PORT_OPTION, null);
176*c3437056SNickeau                if ($portOptionName === null) {
177*c3437056SNickeau                    fwrite(STDERR, "The host port is mandatory");
178*c3437056SNickeau                    return;
179*c3437056SNickeau                }
180*c3437056SNickeau                $_SERVER['SERVER_PORT'] = $portOptionName;
181*c3437056SNickeau                $this->index($startPath, $force, $depth);
182*c3437056SNickeau                break;
183*c3437056SNickeau            case self::METADATA_TO_FRONTMATTER:
184*c3437056SNickeau                $startPath = $this->getStartPath($args);
185*c3437056SNickeau                $this->frontmatter($startPath, $depth);
186*c3437056SNickeau                break;
18771f916b9Sgerardnico            case self::ANALYTICS:
188*c3437056SNickeau                $startPath = $this->getStartPath($args);
189007225e5Sgerardnico                $output = $options->getOpt('output', '');
190007225e5Sgerardnico                //if ($output == '-') $output = 'php://stdout';
191*c3437056SNickeau                $this->analytics($startPath, $output, $depth);
19271f916b9Sgerardnico                break;
19371f916b9Sgerardnico            case self::SYNC:
194*c3437056SNickeau                $this->deleteNonExistingPageFromDatabase();
195*c3437056SNickeau                break;
196*c3437056SNickeau            case self::PLUGINS_TO_UPDATE:
197*c3437056SNickeau                /**
198*c3437056SNickeau                 * Endpoint:
199*c3437056SNickeau                 * self::EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name)
200*c3437056SNickeau                 * `http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php?fmt=php&ext[]=`.urlencode($name)
201*c3437056SNickeau                 */
202*c3437056SNickeau                $pluginList = plugin_list('', true);
203*c3437056SNickeau                /* @var helper_plugin_extension_extension $extension */
204*c3437056SNickeau                $extension = $this->loadHelper('extension_extension');
205*c3437056SNickeau                foreach ($pluginList as $name) {
206*c3437056SNickeau                    $extension->setExtension($name);
207*c3437056SNickeau                    if ($extension->updateAvailable()) {
208*c3437056SNickeau                        echo "The extension $name should be updated";
209*c3437056SNickeau                    }
210*c3437056SNickeau                }
21171f916b9Sgerardnico                break;
21271f916b9Sgerardnico            default:
213*c3437056SNickeau                if ($cmd !== "") {
214*c3437056SNickeau                    fwrite(STDERR, "Combo: Command unknown (" . $cmd . ")");
215*c3437056SNickeau                } else {
216*c3437056SNickeau                    echo $options->help();
217*c3437056SNickeau                }
218*c3437056SNickeau                exit(1);
21971f916b9Sgerardnico        }
220007225e5Sgerardnico
221007225e5Sgerardnico
222007225e5Sgerardnico    }
223007225e5Sgerardnico
224007225e5Sgerardnico    /**
22571f916b9Sgerardnico     * @param array $namespaces
226*c3437056SNickeau     * @param bool $rebuild
227007225e5Sgerardnico     * @param int $depth recursion depth. 0 for unlimited
228*c3437056SNickeau     * @throws ExceptionCombo
229007225e5Sgerardnico     */
230*c3437056SNickeau    private function index($namespaces = array(), $rebuild = false, $depth = 0)
231*c3437056SNickeau    {
232*c3437056SNickeau
233*c3437056SNickeau        /**
234*c3437056SNickeau         * Run as admin to overcome the fact that
235*c3437056SNickeau         * anonymous user cannot see all links and backlinks
236*c3437056SNickeau         */
237*c3437056SNickeau        global $USERINFO;
238*c3437056SNickeau        $USERINFO['grps'] = array('admin');
239*c3437056SNickeau        global $INPUT;
240*c3437056SNickeau        $INPUT->server->set('REMOTE_USER', "cli");
241*c3437056SNickeau
242*c3437056SNickeau        $pages = FsWikiUtility::getPages($namespaces, $depth);
243*c3437056SNickeau
244*c3437056SNickeau        $pageCounter = 0;
245*c3437056SNickeau        $totalNumberOfPages = sizeof($pages);
246*c3437056SNickeau        while ($pageArray = array_shift($pages)) {
247*c3437056SNickeau            $id = $pageArray['id'];
248*c3437056SNickeau            /**
249*c3437056SNickeau             * Indexing the page start the database replication
250*c3437056SNickeau             * See {@link action_plugin_combo_fulldatabasereplication}
251*c3437056SNickeau             */
252*c3437056SNickeau            $pageCounter++;
253*c3437056SNickeau            try {
254*c3437056SNickeau                /**
255*c3437056SNickeau                 * If the page does not need to be indexed, there is no run
256*c3437056SNickeau                 * and false is returned
257*c3437056SNickeau                 */
258*c3437056SNickeau                $indexedOrNot = idx_addPage($id, true, true);
259*c3437056SNickeau                if ($indexedOrNot) {
260*c3437056SNickeau                    LogUtility::msg("The page {$id} ($pageCounter / $totalNumberOfPages) was indexed and replicated", LogUtility::LVL_MSG_INFO);
261*c3437056SNickeau                } else {
262*c3437056SNickeau                    LogUtility::msg("The page {$id} ($pageCounter / $totalNumberOfPages) has an error", LogUtility::LVL_MSG_ERROR);
263*c3437056SNickeau                }
264*c3437056SNickeau            } catch (ExceptionComboRuntime $e) {
265*c3437056SNickeau                LogUtility::msg("The page {$id} ($pageCounter / $totalNumberOfPages) has an error: " . $e->getMessage(), LogUtility::LVL_MSG_ERROR);
266*c3437056SNickeau            }
267*c3437056SNickeau        }
268*c3437056SNickeau        /**
269*c3437056SNickeau         * Process all backlinks
270*c3437056SNickeau         */
271*c3437056SNickeau        echo "Processing Replication Request\n";
272*c3437056SNickeau        Event::dispatchEvent(PHP_INT_MAX);
273*c3437056SNickeau
274*c3437056SNickeau    }
275*c3437056SNickeau
276*c3437056SNickeau    private function analytics($namespaces = array(), $output = null, $depth = 0)
277007225e5Sgerardnico    {
278007225e5Sgerardnico
279007225e5Sgerardnico        $fileHandle = null;
280007225e5Sgerardnico        if (!empty($output)) {
281007225e5Sgerardnico            $fileHandle = @fopen($output, 'w');
282007225e5Sgerardnico            if (!$fileHandle) $this->fatal("Failed to open $output");
283007225e5Sgerardnico        }
284007225e5Sgerardnico
28537748cd8SNickeau        /**
28637748cd8SNickeau         * Run as admin to overcome the fact that
28737748cd8SNickeau         * anonymous user cannot see all links and backlinks
28837748cd8SNickeau         */
28937748cd8SNickeau        global $USERINFO;
29037748cd8SNickeau        $USERINFO['grps'] = array('admin');
29137748cd8SNickeau        global $INPUT;
29237748cd8SNickeau        $INPUT->server->set('REMOTE_USER', "cli");
29337748cd8SNickeau
29437748cd8SNickeau        $pages = FsWikiUtility::getPages($namespaces, $depth);
295007225e5Sgerardnico
296007225e5Sgerardnico
297007225e5Sgerardnico        if (!empty($fileHandle)) {
298007225e5Sgerardnico            $header = array(
299007225e5Sgerardnico                'id',
300007225e5Sgerardnico                'backlinks',
301007225e5Sgerardnico                'broken_links',
302007225e5Sgerardnico                'changes',
303007225e5Sgerardnico                'chars',
304007225e5Sgerardnico                'external_links',
305007225e5Sgerardnico                'external_medias',
306007225e5Sgerardnico                'h1',
307007225e5Sgerardnico                'h2',
308007225e5Sgerardnico                'h3',
309007225e5Sgerardnico                'h4',
310007225e5Sgerardnico                'h5',
311007225e5Sgerardnico                'internal_links',
312007225e5Sgerardnico                'internal_medias',
313007225e5Sgerardnico                'words',
314007225e5Sgerardnico                'score'
315007225e5Sgerardnico            );
316007225e5Sgerardnico            fwrite($fileHandle, implode(",", $header) . PHP_EOL);
317007225e5Sgerardnico        }
3189da76789Sgerardnico        $pageCounter = 0;
319e8b2ff59SNickeau        $totalNumberOfPages = sizeof($pages);
320*c3437056SNickeau        while ($pageArray = array_shift($pages)) {
321*c3437056SNickeau            $id = $pageArray['id'];
322*c3437056SNickeau            $page = Page::createPageFromId($id);
323*c3437056SNickeau
324007225e5Sgerardnico
3259da76789Sgerardnico            $pageCounter++;
326*c3437056SNickeau            echo "Analytics Processing for the page {$id} ($pageCounter / $totalNumberOfPages)\n";
327007225e5Sgerardnico
328*c3437056SNickeau            /**
329*c3437056SNickeau             * Analytics
330*c3437056SNickeau             */
331*c3437056SNickeau            $analytics = $page->getAnalyticsDocument();
332*c3437056SNickeau            $data = $analytics->getOrProcessContent()->toArray();
333*c3437056SNickeau
334007225e5Sgerardnico            if (!empty($fileHandle)) {
335*c3437056SNickeau                $statistics = $data[AnalyticsDocument::STATISTICS];
336007225e5Sgerardnico                $row = array(
337007225e5Sgerardnico                    'id' => $id,
338*c3437056SNickeau                    'backlinks' => $statistics[BacklinkCount::getPersistentName()],
339*c3437056SNickeau                    'broken_links' => $statistics[AnalyticsDocument::INTERNAL_LINK_BROKEN_COUNT],
340*c3437056SNickeau                    'changes' => $statistics[AnalyticsDocument::EDITS_COUNT],
341*c3437056SNickeau                    'chars' => $statistics[AnalyticsDocument::CHAR_COUNT],
342*c3437056SNickeau                    'external_links' => $statistics[AnalyticsDocument::EXTERNAL_LINK_COUNT],
343*c3437056SNickeau                    'external_medias' => $statistics[AnalyticsDocument::EXTERNAL_MEDIA_COUNT],
344*c3437056SNickeau                    PageH1::PROPERTY_NAME => $statistics[AnalyticsDocument::HEADING_COUNT][PageH1::PROPERTY_NAME],
345*c3437056SNickeau                    'h2' => $statistics[AnalyticsDocument::HEADING_COUNT]['h2'],
346*c3437056SNickeau                    'h3' => $statistics[AnalyticsDocument::HEADING_COUNT]['h3'],
347*c3437056SNickeau                    'h4' => $statistics[AnalyticsDocument::HEADING_COUNT]['h4'],
348*c3437056SNickeau                    'h5' => $statistics[AnalyticsDocument::HEADING_COUNT]['h5'],
349*c3437056SNickeau                    'internal_links' => $statistics[AnalyticsDocument::INTERNAL_LINK_COUNT],
350*c3437056SNickeau                    'internal_medias' => $statistics[AnalyticsDocument::INTERNAL_MEDIA_COUNT],
351*c3437056SNickeau                    'words' => $statistics[AnalyticsDocument::WORD_COUNT],
352*c3437056SNickeau                    'low' => $data[AnalyticsDocument::QUALITY]['low']
353007225e5Sgerardnico                );
354007225e5Sgerardnico                fwrite($fileHandle, implode(",", $row) . PHP_EOL);
355007225e5Sgerardnico            }
356*c3437056SNickeau
357007225e5Sgerardnico        }
358007225e5Sgerardnico        if (!empty($fileHandle)) {
359007225e5Sgerardnico            fclose($fileHandle);
360007225e5Sgerardnico        }
361007225e5Sgerardnico
362007225e5Sgerardnico    }
36371f916b9Sgerardnico
364325fe0c5Sgerardnico
365*c3437056SNickeau    private function deleteNonExistingPageFromDatabase()
36671f916b9Sgerardnico    {
367*c3437056SNickeau        LogUtility::msg("Starting: Deleting non-existing page from database");
368*c3437056SNickeau        $sqlite = Sqlite::createOrGetSqlite();
369*c3437056SNickeau        $request = $sqlite
370*c3437056SNickeau            ->createRequest()
371*c3437056SNickeau            ->setQuery("select id as \"id\" from pages");
372*c3437056SNickeau        $rows = [];
373*c3437056SNickeau        try {
374*c3437056SNickeau            $rows = $request
375*c3437056SNickeau                ->execute()
376*c3437056SNickeau                ->getRows();
377*c3437056SNickeau        } catch (ExceptionCombo $e) {
378*c3437056SNickeau            LogUtility::msg("Error while getting the id pages. {$e->getMessage()}");
379*c3437056SNickeau            return;
380*c3437056SNickeau        } finally {
381*c3437056SNickeau            $request->close();
38271f916b9Sgerardnico        }
383*c3437056SNickeau        $counter = 0;
384*c3437056SNickeau        foreach ($rows as $row) {
385*c3437056SNickeau            $counter++;
386*c3437056SNickeau            $id = $row['id'];
38771f916b9Sgerardnico            if (!page_exists($id)) {
38871f916b9Sgerardnico                echo 'Page does not exist on the file system. Deleted from the database (' . $id . ")\n";
389*c3437056SNickeau                Page::createPageFromId($id)->getDatabasePage()->delete();
390*c3437056SNickeau            }
391*c3437056SNickeau        }
392*c3437056SNickeau        LogUtility::msg("Sync finished ($counter pages checked)");
393*c3437056SNickeau
394*c3437056SNickeau
395*c3437056SNickeau    }
396*c3437056SNickeau
397*c3437056SNickeau    private function frontmatter($namespaces, $depth)
398*c3437056SNickeau    {
399*c3437056SNickeau        $pages = FsWikiUtility::getPages($namespaces, $depth);
400*c3437056SNickeau        $pageCounter = 0;
401*c3437056SNickeau        $totalNumberOfPages = sizeof($pages);
402*c3437056SNickeau        $pagesWithChanges = [];
403*c3437056SNickeau        $pagesWithError = [];
404*c3437056SNickeau        $pagesWithOthers = [];
405*c3437056SNickeau        $notChangedCounter = 0;
406*c3437056SNickeau        while ($pageArray = array_shift($pages)) {
407*c3437056SNickeau            $id = $pageArray['id'];
408*c3437056SNickeau            $page = Page::createPageFromId($id);
409*c3437056SNickeau            $pageCounter++;
410*c3437056SNickeau            LogUtility::msg("Processing page {$id} ($pageCounter / $totalNumberOfPages) ", LogUtility::LVL_MSG_INFO);
411*c3437056SNickeau            try {
412*c3437056SNickeau                $message = MetadataFrontmatterStore::createFromPage($page)
413*c3437056SNickeau                    ->sync();
414*c3437056SNickeau                switch ($message->getStatus()) {
415*c3437056SNickeau                    case syntax_plugin_combo_frontmatter::UPDATE_EXIT_CODE_NOT_CHANGED:
416*c3437056SNickeau                        $notChangedCounter++;
417*c3437056SNickeau                        break;
418*c3437056SNickeau                    case syntax_plugin_combo_frontmatter::UPDATE_EXIT_CODE_DONE:
419*c3437056SNickeau                        $pagesWithChanges[] = $id;
420*c3437056SNickeau                        break;
421*c3437056SNickeau                    case syntax_plugin_combo_frontmatter::UPDATE_EXIT_CODE_ERROR:
422*c3437056SNickeau                        $pagesWithError[$id] = $message->getPlainTextContent();
423*c3437056SNickeau                        break;
424*c3437056SNickeau                    default:
425*c3437056SNickeau                        $pagesWithOthers[$id] = $message->getPlainTextContent();
426*c3437056SNickeau                        break;
427*c3437056SNickeau
428*c3437056SNickeau                }
429*c3437056SNickeau            } catch (ExceptionCombo $e) {
430*c3437056SNickeau                $pagesWithError[$id] = $e->getMessage();
431*c3437056SNickeau            }
432*c3437056SNickeau
433*c3437056SNickeau        }
434*c3437056SNickeau
435*c3437056SNickeau        echo "\n";
436*c3437056SNickeau        echo "Result:\n";
437*c3437056SNickeau        echo "$notChangedCounter pages without any frontmatter modifications\n";
438*c3437056SNickeau
439*c3437056SNickeau        if (sizeof($pagesWithError) > 0) {
440*c3437056SNickeau            echo "\n";
441*c3437056SNickeau            echo "The following pages had errors\n";
442*c3437056SNickeau            $pageCounter = 0;
443*c3437056SNickeau            $totalNumberOfPages = sizeof($pagesWithError);
444*c3437056SNickeau            foreach ($pagesWithError as $id => $message) {
445*c3437056SNickeau                $pageCounter++;
446*c3437056SNickeau                LogUtility::msg("Page {$id} ($pageCounter / $totalNumberOfPages): " . $message, LogUtility::LVL_MSG_ERROR);
447*c3437056SNickeau            }
448*c3437056SNickeau        } else {
449*c3437056SNickeau            echo "No error\n";
450*c3437056SNickeau        }
451*c3437056SNickeau
452*c3437056SNickeau        if (sizeof($pagesWithChanges) > 0) {
453*c3437056SNickeau            echo "\n";
454*c3437056SNickeau            echo "The following pages had changed:\n";
455*c3437056SNickeau            $pageCounter = 0;
456*c3437056SNickeau            $totalNumberOfPages = sizeof($pagesWithChanges);
457*c3437056SNickeau            foreach ($pagesWithChanges as $id) {
458*c3437056SNickeau                $pageCounter++;
459*c3437056SNickeau                LogUtility::msg("Page {$id} ($pageCounter / $totalNumberOfPages) ", LogUtility::LVL_MSG_ERROR);
460*c3437056SNickeau            }
461*c3437056SNickeau        } else {
462*c3437056SNickeau            echo "No changes\n";
463*c3437056SNickeau        }
464*c3437056SNickeau
465*c3437056SNickeau        if (sizeof($pagesWithOthers) > 0) {
466*c3437056SNickeau            echo "\n";
467*c3437056SNickeau            echo "The following pages had an other status";
468*c3437056SNickeau            $pageCounter = 0;
469*c3437056SNickeau            $totalNumberOfPages = sizeof($pagesWithOthers);
470*c3437056SNickeau            foreach ($pagesWithOthers as $id => $message) {
471*c3437056SNickeau                $pageCounter++;
472*c3437056SNickeau                LogUtility::msg("Page {$id} ($pageCounter / $totalNumberOfPages) " . $message, LogUtility::LVL_MSG_ERROR);
473*c3437056SNickeau            }
47471f916b9Sgerardnico        }
47571f916b9Sgerardnico    }
47671f916b9Sgerardnico
477*c3437056SNickeau    private function getStartPath($args)
478*c3437056SNickeau    {
479*c3437056SNickeau        $sizeof = sizeof($args);
480*c3437056SNickeau        switch ($sizeof) {
481*c3437056SNickeau            case 0:
482*c3437056SNickeau                fwrite(STDERR, "The start path is mandatory and was not given");
483*c3437056SNickeau                exit(1);
484*c3437056SNickeau            case 1:
485*c3437056SNickeau                $startPath = $args[0];
486*c3437056SNickeau                if (!in_array($startPath, [":", "/"])) {
487*c3437056SNickeau                    // cleanId would return blank for a root
488*c3437056SNickeau                    $startPath = cleanID($startPath);
489*c3437056SNickeau                }
490*c3437056SNickeau                break;
491*c3437056SNickeau            default:
492*c3437056SNickeau                fwrite(STDERR, "Too much arguments given $sizeof");
493*c3437056SNickeau                exit(1);
494*c3437056SNickeau        }
495*c3437056SNickeau        return $startPath;
49671f916b9Sgerardnico    }
497007225e5Sgerardnico}
498