-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPicoFilePrefixes.php
166 lines (149 loc) · 5.55 KB
/
PicoFilePrefixes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
/**
* This file is part of Pico. It's copyrighted by the contributors recorded
* in the version control history of the file, available from the following
* original location:
*
* <https://github.com/PhrozenByte/pico-file-prefixes/blob/master/PicoFilePrefixes.php>
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/
/**
* Pico file prefixes plugin - drop file prefixes from page URLs
*
* PicoFilePrefixes removes file prefixes (e.g. date identifiers) from page
* URLs (e.g. http://example.com/20160707.page --> http://example.com/page).
* This makes organizing your files on the filesystem easier than ever before,
* while maintaining user-friendly URLs.
*
* @author Daniel Rudolf
* @link http://picocms.org
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.0.0
*/
class PicoFilePrefixes extends AbstractPicoPlugin
{
/**
* API version used by this plugin
*
* @var int
*/
const API_VERSION = 2;
/**
* Regex pattern matching directory paths with prefixed files
*
* @var string
*/
protected $filePathRegex = '';
/**
* List of pages whose URL has been altered
*
* @var array
*/
protected $prefixPages = array();
/**
* Prepares the plugin's configuration and the file path regex
*
* @see DummyPlugin::onConfigLoaded()
*/
public function onConfigLoaded(array &$config)
{
$defaultPluginConfig = array(
'recursiveDirs' => array('blog'),
'dirs' => array()
);
if (!isset($config['PicoFilePrefixes']) || !is_array($config['PicoFilePrefixes'])) {
$config['PicoFilePrefixes'] = $defaultPluginConfig;
$this->filePathRegex = '#^(blog(?:/.+)?)$#';
return;
}
$config['PicoFilePrefixes'] += $defaultPluginConfig;
if (empty($config['PicoFilePrefixes']['recursiveDirs']) && empty($config['PicoFilePrefixes']['dirs'])) {
// disable plugin when no dirs were configured
$this->setEnabled(false);
return;
}
// prepare file path regex
$this->filePathRegex = '#^';
if (!empty($config['PicoFilePrefixes']['recursiveDirs'])) {
if (in_array('.', $config['PicoFilePrefixes']['recursiveDirs'])) {
// enable plugin for any directory
$this->filePathRegex = '#^.+$#';
return;
}
$this->filePathRegex .= '(?:' . implode('|', array_map(function ($recursiveDir) {
return preg_quote($recursiveDir, '#');
}, $config['PicoFilePrefixes']['recursiveDirs'])) . ')(?:/.+)?';
if (!empty($config['PicoFilePrefixes']['dirs'])) {
$this->filePathRegex .= '|';
}
}
if (!empty($config['PicoFilePrefixes']['dirs'])) {
$this->filePathRegex .= implode('|', array_map(function ($dir) {
return preg_quote($dir, '#');
}, $config['PicoFilePrefixes']['dirs']));
}
$this->filePathRegex .= '$#';
}
/**
* Rewrites shortened URLs to their matching file on the filesystem
*
* @see DummyPlugin::onRequestFile()
*/
public function onRequestFile(&$file)
{
if (file_exists($file)) {
// don't do anything when the requested file exists
return;
}
$contentDir = $this->getConfig('content_dir');
$contentDirLength = strlen($contentDir);
if (substr($file, 0, $contentDirLength) === $contentDir) {
$filePath = dirname(substr($file, $contentDirLength));
if (preg_match($this->filePathRegex, $filePath)) {
$filePattern = (($filePath !== '.') ? $filePath . '/' : '') . '*.' . basename($file);
$matchingFiles = glob($contentDir . $filePattern);
if ($matchingFiles) {
// use the last matching file in alphabetic order
// (i.e. the "highest" prefix wins)
$file = end($matchingFiles);
}
}
}
}
/**
* Alters URLs of prefixed files
*
* @see DummyPlugin::onPagesLoaded()
*/
public function onPagesLoaded(array &$pages)
{
foreach ($pages as &$pageData) {
$filePath = dirname($pageData['id']);
if (preg_match($this->filePathRegex, $filePath)) {
$file = basename($pageData['id']);
if (($removeIdentifierPos = strpos($file, '.')) === false) {
// don't alter URLs of files without a prefix
continue;
}
$file = (($filePath !== '.') ? $filePath . '/' : '') . substr($file, $removeIdentifierPos + 1);
if (isset($pages[$file])) {
// don't do anything when a file of this name exists
continue;
}
if (isset($this->prefixPages[$file])) {
// found a conflicting file
// alter the URL of the file with the "highest" prefix only
if (strcmp($pageData['id'], $this->prefixPages[$file]['id']) <= 0) {
continue;
}
// restore the URL of the previously altered page
$pages[$this->prefixPages[$file]['id']]['url'] = $this->prefixPages[$file]['url'];
}
$this->prefixPages[$file] = $pageData;
$pageData['url'] = $this->getPageUrl($file);
}
}
}
}