1<?php 2/** 3 * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved. 4 * 5 * This source code is licensed under the GPL license found in the 6 * COPYING file in the root directory of this source tree. 7 * 8 * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 9 * @author ComboStrap <support@combostrap.com> 10 * 11 */ 12if (!defined('DOKU_INC')) die(); 13 14use ComboStrap\Analytics; 15use splitbrain\phpcli\Options; 16 17require_once(__DIR__ . '/class/Analytics.php'); 18 19/** 20 * The memory of the server 128 is not enough 21 */ 22ini_set('memory_limit', '256M'); 23 24/** 25 * Class cli_plugin_combo 26 * 27 * This is a cli: 28 * https://www.dokuwiki.org/devel:cli_plugins#example 29 * 30 * Usage: 31 * 32 * ``` 33 * docker exec -ti $(CONTAINER) /bin/bash 34 * ./bin/plugin.php combo -c 35 * ``` 36 * or via the IDE 37 * 38 * 39 * Example: 40 * https://www.dokuwiki.org/tips:grapher 41 * 42 */ 43class cli_plugin_combo extends DokuWiki_CLI_Plugin 44{ 45 46 /** 47 * register options and arguments 48 * @param Options $options 49 */ 50 protected function setup(Options $options) 51 { 52 $options->setHelp('Run the analytics process'); 53 $options->registerOption('version', 'print version', 'v'); 54 $options->registerArgument( 55 'namespaces', 56 "If no namespace is given, the root namespace is assumed.", 57 false); 58 $options->registerOption( 59 'output', 60 "Optional, where to store the analytical data as csv eg. a filename.", 61 'o', 'file'); 62 $options->registerOption( 63 'cache', 64 "Optional, returns from the cache if set", 65 'c', false); 66 67 } 68 69 /** 70 * The main entry 71 * @param Options $options 72 */ 73 protected function main(Options $options) 74 { 75 76 $namespaces = array_map('cleanID', $options->getArgs()); 77 if (!count($namespaces)) $namespaces = array(''); //import from top 78 79 $output = $options->getOpt('output', ''); 80 //if ($output == '-') $output = 'php://stdout'; 81 $cache = $options->getOpt('cache', false); 82 83 84 $this->process($namespaces, $output, $cache); 85 86 87 } 88 89 /** 90 * @param $namespaces 91 * @param $output 92 * @param bool $cache 93 * @param int $depth recursion depth. 0 for unlimited 94 */ 95 private function process($namespaces, $output, $cache = false, $depth = 0) 96 { 97 global $conf; 98 99 $fileHandle = null; 100 if (!empty($output)) { 101 $fileHandle = @fopen($output, 'w'); 102 if (!$fileHandle) $this->fatal("Failed to open $output"); 103 } 104 105 // find pages 106 $pages = array(); 107 foreach ($namespaces as $ns) { 108 109 search( 110 $pages, 111 $conf['datadir'], 112 'search_universal', 113 array( 114 'depth' => $depth, 115 'listfiles' => true, 116 'listdirs' => false, 117 'pagesonly' => true, 118 'skipacl' => true, 119 'firsthead' => false, 120 'meta' => false, 121 ), 122 str_replace(':', '/', $ns) 123 ); 124 125 // add the ns start page 126 if ($ns && page_exists($ns)) { 127 $pages[] = array( 128 'id' => $ns, 129 'ns' => getNS($ns), 130 'title' => p_get_first_heading($ns, false), 131 'size' => filesize(wikiFN($ns)), 132 'mtime' => filemtime(wikiFN($ns)), 133 'perm' => 16, 134 'type' => 'f', 135 'level' => 0, 136 'open' => 1, 137 ); 138 } 139 140 } 141 142 143 if (!empty($fileHandle)) { 144 $header = array( 145 'id', 146 'backlinks', 147 'broken_links', 148 'changes', 149 'chars', 150 'external_links', 151 'external_medias', 152 'h1', 153 'h2', 154 'h3', 155 'h4', 156 'h5', 157 'internal_links', 158 'internal_medias', 159 'words', 160 'score' 161 ); 162 fwrite($fileHandle, implode(",", $header) . PHP_EOL); 163 } 164 while ($page = array_shift($pages)) { 165 $id = $page['id']; 166 167 // Run as admin to overcome the fact that 168 // anonymous user cannot set all links and backlinnks 169 global $USERINFO; 170 $USERINFO['grps'] = array('admin'); 171 172 173 echo 'Processing the page ' . $id ."\n"; 174 175 $data = Analytics::getDataAsArray($id, $cache); 176 if (!empty($fileHandle)) { 177 $statistics = $data[Analytics::STATISTICS]; 178 $row = array( 179 'id' => $id, 180 'backlinks' => $statistics[Analytics::INTERNAL_BACKLINKS_COUNT], 181 'broken_links' => $statistics[Analytics::INTERNAL_LINKS_BROKEN_COUNT], 182 'changes' => $statistics[Analytics::EDITS_COUNT], 183 'chars' => $statistics[Analytics::CHARS_COUNT], 184 'external_links' => $statistics[Analytics::EXTERNAL_LINKS_COUNT], 185 'external_medias' => $statistics[Analytics::EXTERNAL_MEDIAS], 186 'h1' => $statistics[Analytics::HEADERS_COUNT]['h1'], 187 'h2' => $statistics[Analytics::HEADERS_COUNT]['h2'], 188 'h3' => $statistics[Analytics::HEADERS_COUNT]['h3'], 189 'h4' => $statistics[Analytics::HEADERS_COUNT]['h4'], 190 'h5' => $statistics[Analytics::HEADERS_COUNT]['h5'], 191 'internal_links' => $statistics[Analytics::INTERNAL_LINKS_COUNT], 192 'internal_medias' => $statistics[Analytics::INTERNAL_MEDIAS_COUNT], 193 'words' => $statistics[Analytics::WORDS_COUNT], 194 'low' => $data[Analytics::QUALITY]['low'] 195 ); 196 fwrite($fileHandle, implode(",", $row) . PHP_EOL); 197 } 198 } 199 if (!empty($fileHandle)) { 200 fclose($fileHandle); 201 } 202 203 } 204} 205