OSDN Git Service

BugTrack/2561 Simpify English words - Page list / Page file list
[pukiwiki/pukiwiki.git] / lib / make_link.php
index 598ce07..b78cb18 100644 (file)
@@ -2,12 +2,29 @@
 // PukiWiki - Yet another WikiWikiWeb clone.
 // make_link.php
 // Copyright
-//   2003-2016 PukiWiki Development Team
+//   2003-2021 PukiWiki Development Team
 //   2001-2002 Originally written by yu-ji
 // License: GPL v2 or (at your option) any later version
 //
 // Hyperlink-related functions
 
+// To get page exists or filetimes without accessing filesystem
+// Type: array (page => filetime)
+$_cached_page_filetime = null;
+
+// Get filetime from cache
+function fast_get_filetime($page)
+{
+       global $_cached_page_filetime;
+       if (is_null($_cached_page_filetime)) {
+               return get_filetime($page);
+       }
+       if (isset($_cached_page_filetime[$page])) {
+               return $_cached_page_filetime[$page];
+       }
+       return get_filetime($page);
+}
+
 // Hyperlink decoration
 function make_link($string, $page = '')
 {
@@ -30,16 +47,18 @@ class InlineConverter
        var $result;
 
        function get_clone($obj) {
-               static $clone_func;
-
-               if (! isset($clone_func)) {
+               static $clone_exists;
+               if (! isset($clone_exists)) {
                        if (version_compare(PHP_VERSION, '5.0.0', '<')) {
-                               $clone_func = create_function('$a', 'return $a;');
+                               $clone_exists = false;
                        } else {
-                               $clone_func = create_function('$a', 'return clone $a;');
+                               $clone_exists = true;
                        }
                }
-               return $clone_func($obj);
+               if ($clone_exists) {
+                       return clone ($obj);
+               }
+               return $obj;
        }
 
        function __clone() {
@@ -64,9 +83,11 @@ class InlineConverter
                                'url_interwiki', // URLs (interwiki definition)
                                'mailto',        // mailto: URL schemes
                                'interwikiname', // InterWikiNames
+                               'autoalias',     // AutoAlias
                                'autolink',      // AutoLinks
                                'bracketname',   // BracketNames
                                'wikiname',      // WikiNames
+                               'autoalias_a',   // AutoAlias(alphabet)
                                'autolink_a',    // AutoLinks(alphabet)
                        );
                }
@@ -96,7 +117,7 @@ class InlineConverter
                $this->page   = $page;
                $this->result = array();
 
-               $string = preg_replace_callback('/' . $this->pattern . '/x',
+               $string = preg_replace_callback('/' . $this->pattern . '/x' . get_preg_u(),
                        array(& $this, 'replace'), $string);
 
                $arr = explode("\x08", make_line_rules(htmlsc($string)));
@@ -120,7 +141,8 @@ class InlineConverter
        function get_objects($string, $page)
        {
                $matches = $arr = array();
-               preg_match_all('/' . $this->pattern . '/x', $string, $matches, PREG_SET_ORDER);
+               preg_match_all('/' . $this->pattern . '/x' . get_preg_u(),
+                       $string, $matches, PREG_SET_ORDER);
                foreach ($matches as $match) {
                        $obj = $this->get_converter($match);
                        if ($obj->set($match, $page) !== FALSE) {
@@ -260,7 +282,7 @@ EOD;
 
                // Re-get true plugin name and patameters (for PHP 4.1.2)
                $matches = array();
-               if (preg_match('/^' . $this->pattern . '/x', $all, $matches)
+               if (preg_match('/^' . $this->pattern . '/x' . get_preg_u(), $all, $matches)
                        && $matches[1] != $this->plain) 
                        list(, $this->plain, $name, $this->param) = $matches;
 
@@ -322,12 +344,10 @@ EOD;
                if (PKWK_ALLOW_RELATIVE_FOOTNOTE_ANCHOR) {
                        $script = '';
                } else {
-                       $script = get_script_uri() . '?' . pagename_urlencode($page);
+                       $script = get_page_uri($page);
                }
-
                $id   = ++$note_id;
                $note = make_link($body);
-               $page = isset($vars['page']) ? rawurlencode($vars['page']) : '';
 
                // Footnote
                $foot_explain[$id] = '<a id="notefoot_' . $id . '" href="' .
@@ -342,7 +362,7 @@ EOD;
                        $title = strip_tags($note);
                        $count = mb_strlen($title, SOURCE_ENCODING);
                        $title = mb_substr($title, 0, PKWK_FOOTNOTE_TITLE_MAX, SOURCE_ENCODING);
-                       $abbr  = (mb_strlen($title) < $count) ? '...' : '';
+                       $abbr  = (PKWK_FOOTNOTE_TITLE_MAX < $count) ? '...' : '';
                        $title = ' title="' . $title . $abbr . '"';
                }
                $name = '<a id="notetext_' . $id . '" href="' . $script .
@@ -541,8 +561,6 @@ EOD;
 
        function set($arr, $page)
        {
-               global $script;
-
                list(, $alias, , $name, $this->param) = $this->splice($arr);
 
                $matches = array();
@@ -551,7 +569,7 @@ EOD;
 
                $url = get_interwiki_url($name, $this->param);
                $this->url = ($url === FALSE) ?
-                       $script . '?' . pagename_urlencode('[[' . $name . ':' . $this->param . ']]') :
+                       get_base_uri() . '?' . pagename_urlencode('[[' . $name . ':' . $this->param . ']]') :
                        htmlsc($url);
 
                return parent::setParam(
@@ -751,30 +769,100 @@ class Link_autolink_a extends Link_autolink
        }
 }
 
+// AutoAlias
+class Link_autoalias extends Link
+{
+       var $forceignorepages = array();
+       var $auto;
+       var $auto_a; // alphabet only
+       var $alias;
+
+       function Link_autoalias($start)
+       {
+               $this->__construct($start);
+       }
+       function __construct($start)
+       {
+               global $autoalias, $aliaspage;
+
+               parent::__construct($start);
+
+               if (! $autoalias || ! file_exists(CACHE_DIR . PKWK_AUTOALIAS_REGEX_CACHE) || $this->page == $aliaspage)
+               {
+                       return;
+               }
+
+               @list($auto, $auto_a, $forceignorepages) = file(CACHE_DIR . PKWK_AUTOALIAS_REGEX_CACHE);
+               $this->auto = $auto;
+               $this->auto_a = $auto_a;
+               $this->forceignorepages = explode("\t", trim($forceignorepages));
+               $this->alias = '';
+       }
+       function get_pattern()
+       {
+               return isset($this->auto) ? '(' . $this->auto . ')' : FALSE;
+       }
+       function get_count()
+       {
+               return 1;
+       }
+       function set($arr,$page)
+       {
+               list($name) = $this->splice($arr);
+               // Ignore pages listed
+               if (in_array($name, $this->forceignorepages) || get_autoalias_right_link($name) == '') {
+                       return FALSE;
+               }
+               return parent::setParam($page,$name,'','pagename',$name);
+       }
+
+       function toString()
+       {
+               $this->alias = get_autoalias_right_link($this->name);
+               if ($this->alias != '') {
+                       $link = '[[' . $this->name . '>' . $this->alias . ']]';
+                       return make_link($link);
+               }
+               return '';
+       }
+}
+
+class Link_autoalias_a extends Link_autoalias
+{
+       function Link_autoalias_a($start)
+       {
+               $this->__construct($start);
+       }
+       function __construct($start)
+       {
+               parent::__construct($start);
+       }
+       function get_pattern()
+       {
+               return isset($this->auto_a) ? '(' . $this->auto_a . ')' : FALSE;
+       }
+}
+
 // Make hyperlink for the page
 function make_pagelink($page, $alias = '', $anchor = '', $refer = '', $isautolink = FALSE)
 {
-       global $script, $vars, $link_compact, $related, $_symbol_noexists;
+       global $vars, $link_compact, $related, $_symbol_noexists;
 
+       $script = get_base_uri();
        $s_page = htmlsc(strip_bracket($page));
        $s_alias = ($alias == '') ? $s_page : $alias;
 
        if ($page == '') return '<a href="' . $anchor . '">' . $s_alias . '</a>';
 
-       $r_page  = pagename_urlencode($page);
-       $r_refer = ($refer == '') ? '' : '&amp;refer=' . rawurlencode($refer);
-
-       if (! isset($related[$page]) && $page !== $vars['page'] && is_page($page))
-               $related[$page] = get_filetime($page);
+       $page_filetime = fast_get_filetime($page);
+       $is_page = $page_filetime !== 0;
+       if (! isset($related[$page]) && $page !== $vars['page'] && $is_page) {
+               $related[$page] = $page_filetime;
+       }
 
-       if ($isautolink || is_page($page)) {
+       if ($isautolink || $is_page) {
                // Hyperlink to the page
-               if ($link_compact) {
-                       $title   = '';
-               } else {
-                       $title   = ' title="' . $s_page . get_pg_passage($page, FALSE) . '"';
-               }
-
+               $attrs = get_filetime_a_attrs($page_filetime);
                // AutoLink marker
                if ($isautolink) {
                        $al_left  = '<!--autolink-->';
@@ -782,26 +870,36 @@ function make_pagelink($page, $alias = '', $anchor = '', $refer = '', $isautolin
                } else {
                        $al_left = $al_right = '';
                }
-
-               return $al_left . '<a ' . 'href="' . $script . '?' . $r_page . $anchor .
-                       '"' . $title . '>' . $s_alias . '</a>' . $al_right;
+               $title_attr_html = '';
+               if ($s_page !== $s_alias) {
+                       $title_attr_html = ' title="' . $s_page . '"';
+               }
+               return $al_left . '<a ' . 'href="' . get_page_uri($page) . $anchor .
+                       '"' . $title_attr_html . ' class="' .
+                       $attrs['class'] . '" data-mtime="' . $attrs['data_mtime'] .
+                       '">' . $s_alias . '</a>' . $al_right;
        } else {
                // Support Page redirection
+               $r_page  = rawurlencode($page);
+               $r_refer = ($refer == '') ? '' : '&amp;refer=' . rawurlencode($refer);
                $redirect_page = get_pagename_on_redirect($page);
                if ($redirect_page !== false) {
                        return make_pagelink($redirect_page, $s_alias);
                }
                // Dangling link
                if (PKWK_READONLY) return $s_alias; // No dacorations
-
-               $retval = $s_alias . '<a href="' .
-                       $script . '?cmd=edit&amp;page=' . $r_page . $r_refer . '">' .
-                       $_symbol_noexists . '</a>';
-
-               if ($link_compact) {
+               $symbol_html = '';
+               if ($_symbol_noexists !== '') {
+                       $symbol_html = '<span style="user-select:none;">' .
+                               htmlsc($_symbol_noexists) . '</span>';
+               }
+               $href = $script . '?cmd=edit&amp;page=' . $r_page . $r_refer;
+               if ($link_compact && $_symbol_noexists != '') {
+                       $retval = '<a href="' . $href . '">' . $_symbol_noexists . '</a>';
                        return $retval;
                } else {
-                       return '<span class="noexists">' . $retval . '</span>';
+                       $retval = '<a href="' . $href . '">' . $s_alias . '</a>';
+                       return '<span class="noexists">' . $retval . $symbol_html . '</span>';
                }
        }
 }
@@ -815,7 +913,7 @@ function get_fullname($name, $refer)
        if ($name == '' || $name == './') return $refer;
 
        // Absolute path
-       if ($name{0} == '/') {
+       if ($name[0] == '/') {
                $name = substr($name, 1);
                return ($name == '') ? $defaultpage : $name;
        }
@@ -909,3 +1007,90 @@ function get_interwiki_url($name, $param)
 
        return $url;
 }
+
+function get_autoticketlink_def_page()
+{
+       return 'AutoTicketLinkName';
+}
+
+/**
+ * Get AutoTicketLink - JIRA projects from AutoTiketLinkName page
+ */
+function get_ticketlink_jira_projects()
+{
+       $autoticketlink_def_page = get_autoticketlink_def_page();
+       $active_jira_base_url = null;
+       $jira_projects = array();
+       foreach (get_source($autoticketlink_def_page) as $line) {
+               if (substr($line, 0, 1) !== '-') {
+                       $active_jira_base_url = null;
+                       continue;
+               }
+               $m = null;
+               if (preg_match('/^-\s*(jira)\s+(https?:\/\/[!~*\'();\/?:\@&=+\$,%#\w.-]+)\s*$/', $line, $m)) {
+                       $active_jira_base_url = $m[2];
+               } else if (preg_match('/^--\s*([A-Z][A-Z0-9]{1,10}(?:_[A-Z0-9]{1,10}){0,2})(\s+(.+?))?\s*$/', $line, $m)) {
+                       if ($active_jira_base_url) {
+                               $project_key = $m[1];
+                               $title = isset($m[2]) ? $m[2] : '';
+                               array_push($jira_projects, array(
+                                       'key' => $m[1],
+                                       'title' => $title,
+                                       'base_url' => $active_jira_base_url,
+                               ));
+                       }
+               } else {
+                       $active_jira_base_url = null;
+               }
+       }
+       return $jira_projects;
+}
+
+function init_autoticketlink_def_page()
+{
+       $autoticketlink_def_page = get_autoticketlink_def_page();
+       if (is_page($autoticketlink_def_page)) {
+               return;
+       }
+       $body = <<<EOS
+#freeze
+* AutoTicketLink definition [#def]
+
+Reference: https://pukiwiki.osdn.jp/?AutoTicketLink
+
+ - jira https://site1.example.com/jira/browse/
+ -- AAA Project title \$1
+ -- BBB Project title \$1
+ - jira https://site2.example.com/jira/browse/
+ -- PROJECTA Site2 \$1
+
+ (Default definition) pukiwiki.ini.php
+ $ticket_jira_default_site = array(
+   'title' => 'My JIRA - \$1',
+   'base_url' => 'https://issues.example.com/jira/browse/',
+ );
+EOS;
+       page_write($autoticketlink_def_page, $body);
+}
+
+function init_autoalias_def_page()
+{
+       global $aliaspage; // 'AutoAliasName'
+       $autoticketlink_def_page = get_autoticketlink_def_page();
+       if (is_page($aliaspage)) {
+               return;
+       }
+       $body = <<<EOS
+#freeze
+*AutoAliasName [#qf9311bb]
+AutoAlias definition
+
+Reference: https://pukiwiki.osdn.jp/?AutoAlias
+
+* PukiWiki [#ee87d39e]
+-[[pukiwiki.official>https://pukiwiki.osdn.jp/]]
+-[[pukiwiki.dev>https://pukiwiki.osdn.jp/dev/]]
+EOS;
+       page_write($aliaspage, $body);
+       update_autoalias_cache_file();
+}