splitbrain /
dokuwiki
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * DokuWiki Plugin extension (Helper Component) |
||
| 4 | * |
||
| 5 | * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html |
||
| 6 | * @author Michael Hamann <[email protected]> |
||
| 7 | */ |
||
| 8 | |||
| 9 | /** |
||
| 10 | * Class helper_plugin_extension_list takes care of creating a HTML list of extensions |
||
| 11 | */ |
||
| 12 | class helper_plugin_extension_list extends DokuWiki_Plugin |
||
| 13 | { |
||
| 14 | protected $form = ''; |
||
| 15 | /** @var helper_plugin_extension_gui */ |
||
| 16 | protected $gui; |
||
| 17 | |||
| 18 | /** |
||
| 19 | * Constructor |
||
| 20 | * |
||
| 21 | * loads additional helpers |
||
| 22 | */ |
||
| 23 | public function __construct() |
||
| 24 | { |
||
| 25 | $this->gui = plugin_load('helper', 'extension_gui'); |
||
|
0 ignored issues
–
show
|
|||
| 26 | } |
||
| 27 | |||
| 28 | /** |
||
| 29 | * Initialize the extension table form |
||
| 30 | */ |
||
| 31 | public function startForm() |
||
| 32 | { |
||
| 33 | $this->form .= '<ul class="extensionList">'; |
||
| 34 | } |
||
| 35 | |||
| 36 | /** |
||
| 37 | * Build single row of extension table |
||
| 38 | * |
||
| 39 | * @param helper_plugin_extension_extension $extension The extension that shall be added |
||
| 40 | * @param bool $showinfo Show the info area |
||
| 41 | */ |
||
| 42 | public function addRow(helper_plugin_extension_extension $extension, $showinfo = false) |
||
| 43 | { |
||
| 44 | $this->startRow($extension); |
||
| 45 | $this->populateColumn('legend', $this->makeLegend($extension, $showinfo)); |
||
| 46 | $this->populateColumn('actions', $this->makeActions($extension)); |
||
| 47 | $this->endRow(); |
||
| 48 | } |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Adds a header to the form |
||
| 52 | * |
||
| 53 | * @param string $id The id of the header |
||
| 54 | * @param string $header The content of the header |
||
| 55 | * @param int $level The level of the header |
||
| 56 | */ |
||
| 57 | public function addHeader($id, $header, $level = 2) |
||
| 58 | { |
||
| 59 | $this->form .='<h'.$level.' id="'.$id.'">'.hsc($header).'</h'.$level.'>'.DOKU_LF; |
||
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * Adds a paragraph to the form |
||
| 64 | * |
||
| 65 | * @param string $data The content |
||
| 66 | */ |
||
| 67 | public function addParagraph($data) |
||
| 68 | { |
||
| 69 | $this->form .= '<p>'.hsc($data).'</p>'.DOKU_LF; |
||
| 70 | } |
||
| 71 | |||
| 72 | /** |
||
| 73 | * Add hidden fields to the form with the given data |
||
| 74 | * |
||
| 75 | * @param array $data key-value list of fields and their values to add |
||
| 76 | */ |
||
| 77 | public function addHidden(array $data) |
||
| 78 | { |
||
| 79 | $this->form .= '<div class="no">'; |
||
| 80 | foreach ($data as $key => $value) { |
||
| 81 | $this->form .= '<input type="hidden" name="'.hsc($key).'" value="'.hsc($value).'" />'; |
||
| 82 | } |
||
| 83 | $this->form .= '</div>'.DOKU_LF; |
||
| 84 | } |
||
| 85 | |||
| 86 | /** |
||
| 87 | * Add closing tags |
||
| 88 | */ |
||
| 89 | public function endForm() |
||
| 90 | { |
||
| 91 | $this->form .= '</ul>'; |
||
| 92 | } |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Show message when no results are found |
||
| 96 | */ |
||
| 97 | public function nothingFound() |
||
| 98 | { |
||
| 99 | global $lang; |
||
| 100 | $this->form .= '<li class="notfound">'.$lang['nothingfound'].'</li>'; |
||
| 101 | } |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Print the form |
||
| 105 | * |
||
| 106 | * @param bool $returnonly whether to return html or print |
||
| 107 | */ |
||
| 108 | public function render($returnonly = false) |
||
| 109 | { |
||
| 110 | if ($returnonly) return $this->form; |
||
| 111 | echo $this->form; |
||
| 112 | } |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Start the HTML for the row for the extension |
||
| 116 | * |
||
| 117 | * @param helper_plugin_extension_extension $extension The extension |
||
| 118 | */ |
||
| 119 | private function startRow(helper_plugin_extension_extension $extension) |
||
| 120 | { |
||
| 121 | $this->form .= '<li id="extensionplugin__'.hsc($extension->getID()). |
||
| 122 | '" class="'.$this->makeClass($extension).'">'; |
||
| 123 | } |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Add a column with the given class and content |
||
| 127 | * @param string $class The class name |
||
| 128 | * @param string $html The content |
||
| 129 | */ |
||
| 130 | private function populateColumn($class, $html) |
||
| 131 | { |
||
| 132 | $this->form .= '<div class="'.$class.' col">'.$html.'</div>'.DOKU_LF; |
||
| 133 | } |
||
| 134 | |||
| 135 | /** |
||
| 136 | * End the row |
||
| 137 | */ |
||
| 138 | private function endRow() |
||
| 139 | { |
||
| 140 | $this->form .= '</li>'.DOKU_LF; |
||
| 141 | } |
||
| 142 | |||
| 143 | /** |
||
| 144 | * Generate the link to the plugin homepage |
||
| 145 | * |
||
| 146 | * @param helper_plugin_extension_extension $extension The extension |
||
| 147 | * @return string The HTML code |
||
| 148 | */ |
||
| 149 | public function makeHomepageLink(helper_plugin_extension_extension $extension) |
||
| 150 | { |
||
| 151 | global $conf; |
||
| 152 | $url = $extension->getURL(); |
||
| 153 | if (strtolower(parse_url($url, PHP_URL_HOST)) == 'www.dokuwiki.org') { |
||
| 154 | $linktype = 'interwiki'; |
||
| 155 | } else { |
||
| 156 | $linktype = 'extern'; |
||
| 157 | } |
||
| 158 | $param = array( |
||
| 159 | 'href' => $url, |
||
| 160 | 'title' => $url, |
||
| 161 | 'class' => ($linktype == 'extern') ? 'urlextern' : 'interwiki iw_doku', |
||
| 162 | 'target' => $conf['target'][$linktype], |
||
| 163 | 'rel' => ($linktype == 'extern') ? 'noopener' : '', |
||
| 164 | ); |
||
| 165 | if ($linktype == 'extern' && $conf['relnofollow']) { |
||
| 166 | $param['rel'] = implode(' ', [$param['rel'], 'ugc nofollow']); |
||
| 167 | } |
||
| 168 | $html = ' <a '. buildAttributes($param, true).'>'. |
||
| 169 | $this->getLang('homepage_link').'</a>'; |
||
| 170 | return $html; |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Generate the class name for the row of the extension |
||
| 175 | * |
||
| 176 | * @param helper_plugin_extension_extension $extension The extension object |
||
| 177 | * @return string The class name |
||
| 178 | */ |
||
| 179 | public function makeClass(helper_plugin_extension_extension $extension) |
||
| 180 | { |
||
| 181 | $class = ($extension->isTemplate()) ? 'template' : 'plugin'; |
||
| 182 | if ($extension->isInstalled()) { |
||
| 183 | $class.=' installed'; |
||
| 184 | $class.= ($extension->isEnabled()) ? ' enabled':' disabled'; |
||
| 185 | if ($extension->updateAvailable()) $class .= ' updatable'; |
||
| 186 | } |
||
| 187 | if (!$extension->canModify()) $class.= ' notselect'; |
||
| 188 | if ($extension->isProtected()) $class.= ' protected'; |
||
| 189 | //if($this->showinfo) $class.= ' showinfo'; |
||
| 190 | return $class; |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * Generate a link to the author of the extension |
||
| 195 | * |
||
| 196 | * @param helper_plugin_extension_extension $extension The extension object |
||
| 197 | * @return string The HTML code of the link |
||
| 198 | */ |
||
| 199 | public function makeAuthor(helper_plugin_extension_extension $extension) |
||
| 200 | { |
||
| 201 | if ($extension->getAuthor()) { |
||
| 202 | $mailid = $extension->getEmailID(); |
||
| 203 | if ($mailid) { |
||
| 204 | $url = $this->gui->tabURL('search', array('q' => 'authorid:'.$mailid)); |
||
| 205 | $html = '<a href="'.$url.'" class="author" title="'.$this->getLang('author_hint').'" >'. |
||
| 206 | '<img src="//www.gravatar.com/avatar/'.$mailid. |
||
| 207 | '?s=20&d=mm" width="20" height="20" alt="" /> '. |
||
| 208 | hsc($extension->getAuthor()).'</a>'; |
||
|
0 ignored issues
–
show
It seems like
$extension->getAuthor() targeting helper_plugin_extension_extension::getAuthor() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 209 | } else { |
||
| 210 | $html = '<span class="author">'.hsc($extension->getAuthor()).'</span>'; |
||
|
0 ignored issues
–
show
It seems like
$extension->getAuthor() targeting helper_plugin_extension_extension::getAuthor() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 211 | } |
||
| 212 | $html = '<bdi>'.$html.'</bdi>'; |
||
| 213 | } else { |
||
| 214 | $html = '<em class="author">'.$this->getLang('unknown_author').'</em>'.DOKU_LF; |
||
| 215 | } |
||
| 216 | return $html; |
||
| 217 | } |
||
| 218 | |||
| 219 | /** |
||
| 220 | * Get the link and image tag for the screenshot/thumbnail |
||
| 221 | * |
||
| 222 | * @param helper_plugin_extension_extension $extension The extension object |
||
| 223 | * @return string The HTML code |
||
| 224 | */ |
||
| 225 | public function makeScreenshot(helper_plugin_extension_extension $extension) |
||
| 226 | { |
||
| 227 | $screen = $extension->getScreenshotURL(); |
||
| 228 | $thumb = $extension->getThumbnailURL(); |
||
| 229 | |||
| 230 | if ($screen) { |
||
| 231 | // use protocol independent URLs for images coming from us #595 |
||
| 232 | $screen = str_replace('http://www.dokuwiki.org', '//www.dokuwiki.org', $screen); |
||
| 233 | $thumb = str_replace('http://www.dokuwiki.org', '//www.dokuwiki.org', $thumb); |
||
| 234 | |||
| 235 | $title = sprintf($this->getLang('screenshot'), hsc($extension->getDisplayName())); |
||
| 236 | $img = '<a href="'.hsc($screen).'" target="_blank" class="extension_screenshot">'. |
||
| 237 | '<img alt="'.$title.'" width="120" height="70" src="'.hsc($thumb).'" />'. |
||
| 238 | '</a>'; |
||
| 239 | } elseif ($extension->isTemplate()) { |
||
| 240 | $img = '<img alt="" width="120" height="70" src="'.DOKU_BASE. |
||
| 241 | 'lib/plugins/extension/images/template.png" />'; |
||
| 242 | } else { |
||
| 243 | $img = '<img alt="" width="120" height="70" src="'.DOKU_BASE. |
||
| 244 | 'lib/plugins/extension/images/plugin.png" />'; |
||
| 245 | } |
||
| 246 | $html = '<div class="screenshot" >'.$img.'<span></span></div>'.DOKU_LF; |
||
| 247 | return $html; |
||
| 248 | } |
||
| 249 | |||
| 250 | /** |
||
| 251 | * Extension main description |
||
| 252 | * |
||
| 253 | * @param helper_plugin_extension_extension $extension The extension object |
||
| 254 | * @param bool $showinfo Show the info section |
||
| 255 | * @return string The HTML code |
||
| 256 | */ |
||
| 257 | public function makeLegend(helper_plugin_extension_extension $extension, $showinfo = false) |
||
| 258 | { |
||
| 259 | $html = '<div>'; |
||
| 260 | $html .= '<h2>'; |
||
| 261 | $html .= sprintf( |
||
| 262 | $this->getLang('extensionby'), |
||
| 263 | '<bdi>'.hsc($extension->getDisplayName()).'</bdi>', |
||
| 264 | $this->makeAuthor($extension) |
||
| 265 | ); |
||
| 266 | $html .= '</h2>'.DOKU_LF; |
||
| 267 | |||
| 268 | $html .= $this->makeScreenshot($extension); |
||
| 269 | |||
| 270 | $popularity = $extension->getPopularity(); |
||
| 271 | if ($popularity !== false && !$extension->isBundled()) { |
||
| 272 | $popularityText = sprintf($this->getLang('popularity'), round($popularity*100, 2)); |
||
| 273 | $html .= '<div class="popularity" title="'.$popularityText.'">'. |
||
| 274 | '<div style="width: '.($popularity * 100).'%;">'. |
||
| 275 | '<span class="a11y">'.$popularityText.'</span>'. |
||
| 276 | '</div></div>'.DOKU_LF; |
||
| 277 | } |
||
| 278 | |||
| 279 | if ($extension->getDescription()) { |
||
| 280 | $html .= '<p><bdi>'; |
||
| 281 | $html .= hsc($extension->getDescription()).' '; |
||
| 282 | $html .= '</bdi></p>'.DOKU_LF; |
||
| 283 | } |
||
| 284 | |||
| 285 | $html .= $this->makeLinkbar($extension); |
||
| 286 | |||
| 287 | if ($showinfo) { |
||
| 288 | $url = $this->gui->tabURL(''); |
||
| 289 | $class = 'close'; |
||
| 290 | } else { |
||
| 291 | $url = $this->gui->tabURL('', array('info' => $extension->getID())); |
||
| 292 | $class = ''; |
||
| 293 | } |
||
| 294 | $html .= ' <a href="'.$url.'#extensionplugin__'.$extension->getID(). |
||
| 295 | '" class="info '.$class.'" title="'.$this->getLang('btn_info'). |
||
| 296 | '" data-extid="'.$extension->getID().'">'.$this->getLang('btn_info').'</a>'; |
||
| 297 | |||
| 298 | if ($showinfo) { |
||
| 299 | $html .= $this->makeInfo($extension); |
||
| 300 | } |
||
| 301 | $html .= $this->makeNoticeArea($extension); |
||
| 302 | $html .= '</div>'.DOKU_LF; |
||
| 303 | return $html; |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * Generate the link bar HTML code |
||
| 308 | * |
||
| 309 | * @param helper_plugin_extension_extension $extension The extension instance |
||
| 310 | * @return string The HTML code |
||
| 311 | */ |
||
| 312 | public function makeLinkbar(helper_plugin_extension_extension $extension) |
||
| 313 | { |
||
| 314 | global $conf; |
||
| 315 | $html = '<div class="linkbar">'; |
||
| 316 | $html .= $this->makeHomepageLink($extension); |
||
| 317 | |||
| 318 | $bugtrackerURL = $extension->getBugtrackerURL(); |
||
| 319 | if ($bugtrackerURL) { |
||
| 320 | if (strtolower(parse_url($bugtrackerURL, PHP_URL_HOST)) == 'www.dokuwiki.org') { |
||
| 321 | $linktype = 'interwiki'; |
||
| 322 | } else { |
||
| 323 | $linktype = 'extern'; |
||
| 324 | } |
||
| 325 | $param = array( |
||
| 326 | 'href' => $bugtrackerURL, |
||
| 327 | 'title' => $bugtrackerURL, |
||
| 328 | 'class' => 'bugs', |
||
| 329 | 'target' => $conf['target'][$linktype], |
||
| 330 | 'rel' => ($linktype == 'extern') ? 'noopener' : '', |
||
| 331 | ); |
||
| 332 | if ($conf['relnofollow']) { |
||
| 333 | $param['rel'] = implode(' ', [$param['rel'], 'ugc nofollow']); |
||
| 334 | } |
||
| 335 | $html .= ' <a '.buildAttributes($param, true).'>'. |
||
| 336 | $this->getLang('bugs_features').'</a>'; |
||
| 337 | } |
||
| 338 | if ($extension->getTags()) { |
||
| 339 | $first = true; |
||
| 340 | $html .= ' <span class="tags">'.$this->getLang('tags').' '; |
||
| 341 | foreach ($extension->getTags() as $tag) { |
||
| 342 | if (!$first) { |
||
| 343 | $html .= ', '; |
||
| 344 | } else { |
||
| 345 | $first = false; |
||
| 346 | } |
||
| 347 | $url = $this->gui->tabURL('search', ['q' => 'tag:'.$tag]); |
||
| 348 | $html .= '<bdi><a href="'.$url.'">'.hsc($tag).'</a></bdi>'; |
||
| 349 | } |
||
| 350 | $html .= '</span>'; |
||
| 351 | } |
||
| 352 | $html .= '</div>'.DOKU_LF; |
||
| 353 | return $html; |
||
| 354 | } |
||
| 355 | |||
| 356 | /** |
||
| 357 | * Notice area |
||
| 358 | * |
||
| 359 | * @param helper_plugin_extension_extension $extension The extension |
||
| 360 | * @return string The HTML code |
||
| 361 | */ |
||
| 362 | public function makeNoticeArea(helper_plugin_extension_extension $extension) |
||
| 363 | { |
||
| 364 | $html = ''; |
||
| 365 | $missing_dependencies = $extension->getMissingDependencies(); |
||
| 366 | if (!empty($missing_dependencies)) { |
||
| 367 | $html .= '<div class="msg error">' . |
||
| 368 | sprintf( |
||
| 369 | $this->getLang('missing_dependency'), |
||
| 370 | '<bdi>' . implode(', ', $missing_dependencies) . '</bdi>' |
||
| 371 | ) . |
||
| 372 | '</div>'; |
||
| 373 | } |
||
| 374 | if ($extension->isInWrongFolder()) { |
||
| 375 | $html .= '<div class="msg error">' . |
||
| 376 | sprintf( |
||
| 377 | $this->getLang('wrong_folder'), |
||
| 378 | '<bdi>' . hsc($extension->getInstallName()) . '</bdi>', |
||
| 379 | '<bdi>' . hsc($extension->getBase()) . '</bdi>' |
||
| 380 | ) . |
||
| 381 | '</div>'; |
||
| 382 | } |
||
| 383 | if (($securityissue = $extension->getSecurityIssue()) !== false) { |
||
| 384 | $html .= '<div class="msg error">'. |
||
| 385 | sprintf($this->getLang('security_issue'), '<bdi>'.hsc($securityissue).'</bdi>'). |
||
| 386 | '</div>'; |
||
| 387 | } |
||
| 388 | if (($securitywarning = $extension->getSecurityWarning()) !== false) { |
||
| 389 | $html .= '<div class="msg notify">'. |
||
| 390 | sprintf($this->getLang('security_warning'), '<bdi>'.hsc($securitywarning).'</bdi>'). |
||
| 391 | '</div>'; |
||
| 392 | } |
||
| 393 | if ($extension->updateAvailable()) { |
||
| 394 | $html .= '<div class="msg notify">'. |
||
| 395 | sprintf($this->getLang('update_available'), hsc($extension->getLastUpdate())). |
||
|
0 ignored issues
–
show
It seems like
$extension->getLastUpdate() targeting helper_plugin_extension_extension::getLastUpdate() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 396 | '</div>'; |
||
| 397 | } |
||
| 398 | if ($extension->hasDownloadURLChanged()) { |
||
| 399 | $html .= '<div class="msg notify">' . |
||
| 400 | sprintf( |
||
| 401 | $this->getLang('url_change'), |
||
| 402 | '<bdi>' . hsc($extension->getDownloadURL()) . '</bdi>', |
||
|
0 ignored issues
–
show
It seems like
$extension->getDownloadURL() targeting helper_plugin_extension_...nsion::getDownloadURL() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 403 | '<bdi>' . hsc($extension->getLastDownloadURL()) . '</bdi>' |
||
|
0 ignored issues
–
show
It seems like
$extension->getLastDownloadURL() targeting helper_plugin_extension_...n::getLastDownloadURL() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 404 | ) . |
||
| 405 | '</div>'; |
||
| 406 | } |
||
| 407 | return $html.DOKU_LF; |
||
| 408 | } |
||
| 409 | |||
| 410 | /** |
||
| 411 | * Create a link from the given URL |
||
| 412 | * |
||
| 413 | * Shortens the URL for display |
||
| 414 | * |
||
| 415 | * @param string $url |
||
| 416 | * @return string HTML link |
||
| 417 | */ |
||
| 418 | public function shortlink($url) |
||
| 419 | { |
||
| 420 | $link = parse_url($url); |
||
| 421 | |||
| 422 | $base = $link['host']; |
||
| 423 | if (!empty($link['port'])) $base .= $base.':'.$link['port']; |
||
| 424 | $long = $link['path']; |
||
| 425 | if (!empty($link['query'])) $long .= $link['query']; |
||
| 426 | |||
| 427 | $name = shorten($base, $long, 55); |
||
| 428 | |||
| 429 | $html = '<a href="'.hsc($url).'" class="urlextern">'.hsc($name).'</a>'; |
||
| 430 | return $html; |
||
| 431 | } |
||
| 432 | |||
| 433 | /** |
||
| 434 | * Plugin/template details |
||
| 435 | * |
||
| 436 | * @param helper_plugin_extension_extension $extension The extension |
||
| 437 | * @return string The HTML code |
||
| 438 | */ |
||
| 439 | public function makeInfo(helper_plugin_extension_extension $extension) |
||
| 440 | { |
||
| 441 | $default = $this->getLang('unknown'); |
||
| 442 | $html = '<dl class="details">'; |
||
| 443 | |||
| 444 | $html .= '<dt>'.$this->getLang('status').'</dt>'; |
||
| 445 | $html .= '<dd>'.$this->makeStatus($extension).'</dd>'; |
||
| 446 | |||
| 447 | if ($extension->getDonationURL()) { |
||
| 448 | $html .= '<dt>'.$this->getLang('donate').'</dt>'; |
||
| 449 | $html .= '<dd>'; |
||
| 450 | $html .= '<a href="'.$extension->getDonationURL().'" class="donate">'. |
||
| 451 | $this->getLang('donate_action').'</a>'; |
||
| 452 | $html .= '</dd>'; |
||
| 453 | } |
||
| 454 | |||
| 455 | if (!$extension->isBundled()) { |
||
| 456 | $html .= '<dt>'.$this->getLang('downloadurl').'</dt>'; |
||
| 457 | $html .= '<dd><bdi>'; |
||
| 458 | $html .= ($extension->getDownloadURL() |
||
| 459 | ? $this->shortlink($extension->getDownloadURL()) |
||
| 460 | : $default); |
||
| 461 | $html .= '</bdi></dd>'; |
||
| 462 | |||
| 463 | $html .= '<dt>'.$this->getLang('repository').'</dt>'; |
||
| 464 | $html .= '<dd><bdi>'; |
||
| 465 | $html .= ($extension->getSourcerepoURL() |
||
| 466 | ? $this->shortlink($extension->getSourcerepoURL()) |
||
| 467 | : $default); |
||
| 468 | $html .= '</bdi></dd>'; |
||
| 469 | } |
||
| 470 | |||
| 471 | if ($extension->isInstalled()) { |
||
| 472 | if ($extension->getInstalledVersion()) { |
||
| 473 | $html .= '<dt>'.$this->getLang('installed_version').'</dt>'; |
||
| 474 | $html .= '<dd>'; |
||
| 475 | $html .= hsc($extension->getInstalledVersion()); |
||
|
0 ignored issues
–
show
It seems like
$extension->getInstalledVersion() targeting helper_plugin_extension_...::getInstalledVersion() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 476 | $html .= '</dd>'; |
||
| 477 | } |
||
| 478 | if (!$extension->isBundled()) { |
||
| 479 | $html .= '<dt>'.$this->getLang('install_date').'</dt>'; |
||
| 480 | $html .= '<dd>'; |
||
| 481 | $html .= ($extension->getUpdateDate() |
||
| 482 | ? hsc($extension->getUpdateDate()) |
||
|
0 ignored issues
–
show
It seems like
$extension->getUpdateDate() targeting helper_plugin_extension_extension::getUpdateDate() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 483 | : $this->getLang('unknown')); |
||
| 484 | $html .= '</dd>'; |
||
| 485 | } |
||
| 486 | } |
||
| 487 | if (!$extension->isInstalled() || $extension->updateAvailable()) { |
||
| 488 | $html .= '<dt>'.$this->getLang('available_version').'</dt>'; |
||
| 489 | $html .= '<dd>'; |
||
| 490 | $html .= ($extension->getLastUpdate() |
||
| 491 | ? hsc($extension->getLastUpdate()) |
||
|
0 ignored issues
–
show
It seems like
$extension->getLastUpdate() targeting helper_plugin_extension_extension::getLastUpdate() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 492 | : $this->getLang('unknown')); |
||
| 493 | $html .= '</dd>'; |
||
| 494 | } |
||
| 495 | |||
| 496 | $html .= '<dt>'.$this->getLang('provides').'</dt>'; |
||
| 497 | $html .= '<dd><bdi>'; |
||
| 498 | $html .= ($extension->getTypes() |
||
| 499 | ? hsc(implode(', ', $extension->getTypes())) |
||
| 500 | : $default); |
||
| 501 | $html .= '</bdi></dd>'; |
||
| 502 | |||
| 503 | if (!$extension->isBundled() && $extension->getCompatibleVersions()) { |
||
| 504 | $html .= '<dt>'.$this->getLang('compatible').'</dt>'; |
||
| 505 | $html .= '<dd>'; |
||
| 506 | foreach ($extension->getCompatibleVersions() as $date => $version) { |
||
| 507 | $html .= '<bdi>'.$version['label'].' ('.$date.')</bdi>, '; |
||
| 508 | } |
||
| 509 | $html = rtrim($html, ', '); |
||
| 510 | $html .= '</dd>'; |
||
| 511 | } |
||
| 512 | if ($extension->getDependencies()) { |
||
| 513 | $html .= '<dt>'.$this->getLang('depends').'</dt>'; |
||
| 514 | $html .= '<dd>'; |
||
| 515 | $html .= $this->makeLinkList($extension->getDependencies()); |
||
| 516 | $html .= '</dd>'; |
||
| 517 | } |
||
| 518 | |||
| 519 | if ($extension->getSimilarExtensions()) { |
||
| 520 | $html .= '<dt>'.$this->getLang('similar').'</dt>'; |
||
| 521 | $html .= '<dd>'; |
||
| 522 | $html .= $this->makeLinkList($extension->getSimilarExtensions()); |
||
| 523 | $html .= '</dd>'; |
||
| 524 | } |
||
| 525 | |||
| 526 | if ($extension->getConflicts()) { |
||
| 527 | $html .= '<dt>'.$this->getLang('conflicts').'</dt>'; |
||
| 528 | $html .= '<dd>'; |
||
| 529 | $html .= $this->makeLinkList($extension->getConflicts()); |
||
| 530 | $html .= '</dd>'; |
||
| 531 | } |
||
| 532 | $html .= '</dl>'.DOKU_LF; |
||
| 533 | return $html; |
||
| 534 | } |
||
| 535 | |||
| 536 | /** |
||
| 537 | * Generate a list of links for extensions |
||
| 538 | * |
||
| 539 | * @param array $ext The extensions |
||
| 540 | * @return string The HTML code |
||
| 541 | */ |
||
| 542 | public function makeLinkList($ext) |
||
| 543 | { |
||
| 544 | $html = ''; |
||
| 545 | foreach ($ext as $link) { |
||
| 546 | $html .= '<bdi><a href="'. |
||
| 547 | $this->gui->tabURL('search', array('q'=>'ext:'.$link)).'">'. |
||
| 548 | hsc($link).'</a></bdi>, '; |
||
| 549 | } |
||
| 550 | return rtrim($html, ', '); |
||
| 551 | } |
||
| 552 | |||
| 553 | /** |
||
| 554 | * Display the action buttons if they are possible |
||
| 555 | * |
||
| 556 | * @param helper_plugin_extension_extension $extension The extension |
||
| 557 | * @return string The HTML code |
||
| 558 | */ |
||
| 559 | public function makeActions(helper_plugin_extension_extension $extension) |
||
| 560 | { |
||
| 561 | global $conf; |
||
| 562 | $html = ''; |
||
| 563 | $errors = ''; |
||
| 564 | |||
| 565 | if ($extension->isInstalled()) { |
||
| 566 | if (($canmod = $extension->canModify()) === true) { |
||
| 567 | if (!$extension->isProtected()) { |
||
| 568 | $html .= $this->makeAction('uninstall', $extension); |
||
| 569 | } |
||
| 570 | if ($extension->getDownloadURL()) { |
||
| 571 | if ($extension->updateAvailable()) { |
||
| 572 | $html .= $this->makeAction('update', $extension); |
||
| 573 | } else { |
||
| 574 | $html .= $this->makeAction('reinstall', $extension); |
||
| 575 | } |
||
| 576 | } |
||
| 577 | } else { |
||
| 578 | $errors .= '<p class="permerror">'.$this->getLang($canmod).'</p>'; |
||
| 579 | } |
||
| 580 | |||
| 581 | if (!$extension->isProtected() && !$extension->isTemplate()) { // no enable/disable for templates |
||
| 582 | if ($extension->isEnabled()) { |
||
| 583 | $html .= $this->makeAction('disable', $extension); |
||
| 584 | } else { |
||
| 585 | $html .= $this->makeAction('enable', $extension); |
||
| 586 | } |
||
| 587 | } |
||
| 588 | |||
| 589 | if ($extension->isGitControlled()) { |
||
| 590 | $errors .= '<p class="permerror">'.$this->getLang('git').'</p>'; |
||
| 591 | } |
||
| 592 | |||
| 593 | if ($extension->isEnabled() && |
||
| 594 | in_array('Auth', $extension->getTypes()) && |
||
| 595 | $conf['authtype'] != $extension->getID() |
||
| 596 | ) { |
||
| 597 | $errors .= '<p class="permerror">'.$this->getLang('auth').'</p>'; |
||
| 598 | } |
||
| 599 | } else { |
||
| 600 | if (($canmod = $extension->canModify()) === true) { |
||
| 601 | if ($extension->getDownloadURL()) { |
||
| 602 | $html .= $this->makeAction('install', $extension); |
||
| 603 | } |
||
| 604 | } else { |
||
| 605 | $errors .= '<div class="permerror">'.$this->getLang($canmod).'</div>'; |
||
| 606 | } |
||
| 607 | } |
||
| 608 | |||
| 609 | if (!$extension->isInstalled() && $extension->getDownloadURL()) { |
||
| 610 | $html .= ' <span class="version">'.$this->getLang('available_version').' '; |
||
| 611 | $html .= ($extension->getLastUpdate() |
||
| 612 | ? hsc($extension->getLastUpdate()) |
||
|
0 ignored issues
–
show
It seems like
$extension->getLastUpdate() targeting helper_plugin_extension_extension::getLastUpdate() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 613 | : $this->getLang('unknown')).'</span>'; |
||
| 614 | } |
||
| 615 | |||
| 616 | return $html.' '.$errors.DOKU_LF; |
||
| 617 | } |
||
| 618 | |||
| 619 | /** |
||
| 620 | * Display an action button for an extension |
||
| 621 | * |
||
| 622 | * @param string $action The action |
||
| 623 | * @param helper_plugin_extension_extension $extension The extension |
||
| 624 | * @return string The HTML code |
||
| 625 | */ |
||
| 626 | public function makeAction($action, $extension) |
||
| 627 | { |
||
| 628 | $title = ''; |
||
| 629 | |||
| 630 | switch ($action) { |
||
| 631 | case 'install': |
||
| 632 | case 'reinstall': |
||
| 633 | $title = 'title="'.hsc($extension->getDownloadURL()).'"'; |
||
|
0 ignored issues
–
show
It seems like
$extension->getDownloadURL() targeting helper_plugin_extension_...nsion::getDownloadURL() can also be of type boolean; however, hsc() does only seem to accept string, maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. Loading history...
|
|||
| 634 | break; |
||
| 635 | } |
||
| 636 | |||
| 637 | $classes = 'button '.$action; |
||
| 638 | $name = 'fn['.$action.']['.hsc($extension->getID()).']'; |
||
| 639 | |||
| 640 | $html = '<button class="'.$classes.'" name="'.$name.'" type="submit" '.$title.'>'. |
||
| 641 | $this->getLang('btn_'.$action).'</button> '; |
||
| 642 | return $html; |
||
| 643 | } |
||
| 644 | |||
| 645 | /** |
||
| 646 | * Plugin/template status |
||
| 647 | * |
||
| 648 | * @param helper_plugin_extension_extension $extension The extension |
||
| 649 | * @return string The description of all relevant statusses |
||
| 650 | */ |
||
| 651 | public function makeStatus(helper_plugin_extension_extension $extension) |
||
| 652 | { |
||
| 653 | $status = array(); |
||
| 654 | |||
| 655 | if ($extension->isInstalled()) { |
||
| 656 | $status[] = $this->getLang('status_installed'); |
||
| 657 | if ($extension->isProtected()) { |
||
| 658 | $status[] = $this->getLang('status_protected'); |
||
| 659 | } else { |
||
| 660 | $status[] = $extension->isEnabled() |
||
| 661 | ? $this->getLang('status_enabled') |
||
| 662 | : $this->getLang('status_disabled'); |
||
| 663 | } |
||
| 664 | } else { |
||
| 665 | $status[] = $this->getLang('status_not_installed'); |
||
| 666 | } |
||
| 667 | if (!$extension->canModify()) $status[] = $this->getLang('status_unmodifiable'); |
||
| 668 | if ($extension->isBundled()) $status[] = $this->getLang('status_bundled'); |
||
| 669 | $status[] = $extension->isTemplate() |
||
| 670 | ? $this->getLang('status_template') |
||
| 671 | : $this->getLang('status_plugin'); |
||
| 672 | return implode(', ', $status); |
||
| 673 | } |
||
| 674 | } |
||
| 675 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.