1<?php
2/*
3 * Display Orphans Plugin
4 * Copyright (c) 2016 Jay Jeckel
5 * Licensed under the MIT license: https://opensource.org/licenses/MIT
6 * Permission is granted to use, copy, modify, and distribute the work.
7 * Full license information available in the project LICENSE file.
8*/
9
10if (!defined('DOKU_INC')) { die(); }
11
12require_once(DOKU_INC . 'inc' . '/' . 'search.php');
13require_once(dirname(__FILE__) . '/'. '_local.php');
14use plugin\displayorphans\Util;
15use plugin\displayorphans\Logic;
16
17class helper_plugin_displayorphans extends DokuWiki_Plugin
18{
19    //const PATTERN_LINK = '/\[\[([^\]#\|\>\/\\\\@]+)(?:#[^\]\|]*)?(?:\|[^\]]*)?\]\]/';
20    const PATTERN_LINK = '/\[\[([^\]#\?\|\>\/\\\\@]+)(?:#[^\]\|\?]*)?(?:\?[^\]\|]*)?(?:\|[^\]]*)?\]\]/';
21
22    const IGNORE_BLOCKS = array('/<nowiki>.*?<\/nowiki>/su', '/%%.*?%%/su', '/<php>.*?<\/php>/su', '/<PHP>.*?<\/PHP>/su', '/<html>.*?<\/html>/su', '/<HTML>.*?<\/HTML>/su', '/^( {2,}|\t)[^\*\- ].*?$/mu', '/<code[^>]*?>.*?<\/code>/su', '/<file[^>]*?>.*?<\/file>/su');
23
24    function /* array */ items(/* string */ $datadir, /* string */ $type)
25    {
26        $itemFilterPredicate = array('plugin\displayorphans\Logic', 'is' . ucfirst($type) . 'Page');
27        if (!is_callable($itemFilterPredicate)) { return null; }
28
29        $ignoredPages = Util::asList($this->getConf('ignore_' . $type . '_pages'), ' ');
30        $ignoreNamespaces = Util::asList($this->getConf('ignore_' . $type . '_namespaces'), ' ');
31        $items = $this->findItems($datadir, $itemFilterPredicate, $ignoredPages, $ignoreNamespaces);
32        if (!empty($items)) { if ($this->getConf('sort_table_ascending')) { ksort($items); } else { krsort($items); } }
33        return $items;
34    }
35
36    function /* array */ findItems(/* string */ $datadir, callable $filter = null, array $ignoredPages = null, array $ignoreNamespaces = null)
37    {
38        $all = $this->findAllItems($datadir);
39        $items = array();
40        foreach ($all as $id => $item)
41        { if (empty($filter) || $filter($id, $item, $ignoredPages, $ignoreNamespaces)) { $items[$id] = $item; } }
42        return $items;
43    }
44
45    function /* array */ findAllItems(/* string */ $datadir)
46    {
47        $items = array();
48        search($items, $datadir, array($this, '_filterItem'), null);
49        return $items;
50    }
51
52    function /* bool */ _filterItem(&$data, $base, /* string */ $file, /* string */ $type, $lvl, $opts)
53    {
54        if ($type == 'd') { return true; }
55        else if (!preg_match("/.*\.txt$/", $file)) { return true; }
56
57        $id = pathID($file);
58        if (auth_quickaclcheck($id) < AUTH_READ) { return false; }
59
60        if (array_key_exists($id, $data)) { $data[$id]['exists'] = true; }
61        else { $data[$id] = array('exists' => true, 'count' => 0); }
62
63        $links = $this->_findLinks($file);
64        foreach ($links as $index => $link)
65        {
66            if (array_key_exists($link, $data)) { $data[$link]['count']++; }
67            else { $data[$link] = array('exists' => false, 'count' => 1); }
68        }
69        return true;
70    }
71
72    function /* array */ _findLinks(/* string */ $file)
73    {
74        global $conf;
75
76        $id = pathID($file);
77        $text = @file_get_contents($conf['datadir'] . $file);
78        foreach (self::IGNORE_BLOCKS as $index => $block) { $text = preg_replace($block, '',  $text); }
79        $links = array();
80        preg_match_all(self::PATTERN_LINK, $text, $links);
81        $links = $links[1];
82        foreach($links as $index => $link) { $links[$index] = $this->_resolveLink($id, $link); }
83        return $links;
84    }
85
86    function /* string */ _resolveLink(/* string */ $source, /* string */ $target)
87    { resolve_pageid(getNS($source), $target, $exists); return $target; }
88}
89
90//Setup VIM: ex: et ts=4 enc=utf-8 :
91?>