-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRewriter.php
247 lines (214 loc) · 6.42 KB
/
Rewriter.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
<?php
/**
* Rewriter
*
* A class created to generate Apache RewriteRules based upon source
* and destination URLs
*
* @author OBush.co.uk
*
*/
class Rewriter{
private $includeIfModuleCheck = true;
private $includeTurnOnEngine = true;
private $http301 = true;
private $urls = array();
private $rewrites = '';
public function __construct($includeIfModuleCheck = true, $includeTurnOnEngine = true, $http301 = true){
$this->includeIfModuleCheck = $includeIfModuleCheck;
$this->includeTurnOnEngine = $includeTurnOnEngine;
$this->http301 = $http301;
}
/**
* Generate rewrites based upon an array where 'source' is the key and 'destination' the value
*
* @param array $urls - array in format array('source' => 'destination')
* @throws Exception
* @return string
*/
public function generateRewritesFromArray(array $urls = array()){
if(is_array($urls)){
foreach($urls as $source => $destination){
// Make sure the destination is not an array
if(is_array($destination)){
throw new Exception('Destinations cannot be arrays. Check the destination for: ' . $source);
}
$this->urls[$source] = $destination;
}
// Build the rewrites
return $this->buildRewrites();
}else{
throw new Exception('URLs are not in array format.');
}
}
/**
* Generate rewrites based upon a string with specified separators and linebreaks
*
* @param string $urls
* @param string $separator - character to separate source from destination
* @param string $lineBreak - character to split url pairs
* @throws Exception
* @return string
*/
public function generateRewritesFromString($urls, $separator = ' ', $lineBreak = "\n"){
if(is_array($urls)){
return $this->generateRewritesFromArray($urls);
}else{
// Remove any whitespace at the start/end of the url list
$urls = trim($urls);
// Split URL list by line first
$urlsArray = explode($lineBreak, $urls);
foreach($urlsArray as $url){
// If there is a blank line ignore it
if($url == ''){
continue;
}
// The separator is not used for this URL pair - throw an exception
if(!strpos($url, $separator)){
throw new Exception('URL does not contain valid separator: ' . $url);
}else{
// Split the source and destination parts by the provided separator
// Limit the number of parts after splitting to 2
$splitURLs = explode($separator, $url, 2);
// The separator existed but there were not 2 parts present
if(count($splitURLs) !== 2){
throw new Exception('URL does not contain valid number of separators: ' . $url);
}
// Set the source and destination URLs to the split parts
list($source, $destination) = $splitURLs;
// Remove the leading slash on the source URLs
if(substr($source, 0, 1) == '/'){
$source = substr($source, 1);
}
// Add this URL pair to the URL array
$this->urls[$source] = $destination;
unset($splitURLs);
}
}
unset($urlsArray);
// Build the rewrites
return $this->buildRewrites();
}
}
/**
* Generate the actual rewrites statements
*
* @return string
*/
private function buildRewrites(){
// If we want to add IfModule checks, add the opening tag
if($this->includeIfModuleCheck){
$this->appendIfModuleCheckStart();
}
// If we want to turn the rewrite engine on, add the statement
if($this->includeTurnOnEngine){
$this->appendTurnOnEngine();
}
// Are there actually URLs to rewrite?
if(!empty($this->urls)){
// Loop through the URLs
foreach($this->urls as $source => $destination){
// Check for query strings, as RewriteRule will ignore them
$queryStringPos = strpos($source, '?');
// URL has a query string
if($queryStringPos !== FALSE){
// Grab the query string
$queryString = substr($source, $queryStringPos + 1);
// If there wasn't just a lone ? in the URL
if($queryString != ''){
// Add a RewriteCond for this query string
$this->buildRewriteCondition('QUERY_STRING', $queryString);
}
// RewriteRule matches on the request URI without query strings, so remove the query string
$source = substr($source, 0, $queryStringPos);
}
// Add a RewriteRule for this source / destination
$this->buildRewriteRule($source, $destination);
}
}
// If we are adding the check for mod_rewrite.c add the closing tag
if($this->includeIfModuleCheck){
$this->appendIfModuleCheckEnd();
}
// Return our rewrites
return $this->rewrites;
}
/**
* Add a new line to the rewrites
*
* @param unknown_type $line
*/
private function appendLineToRewrites($line){
$this->rewrites .= "\n" . $line;
}
/**
* Add the check for the mod_rewrite.c module
*/
private function appendIfModuleCheckStart(){
$string = '<IfModule mod_rewrite.c>';
$this->appendLineToRewrites($string);
}
/**
* Add the closing tag for the check for mod_rewrite.c
*/
private function appendIfModuleCheckEnd(){
$string = '</IfModule>';
$this->appendLineToRewrites($string);
}
/**
* Add a line for turning on RewriteEngine
*/
private function appendTurnOnEngine(){
$string = 'RewriteEngine on';
$this->appendLineToRewrites($string);
}
/**
* Surround any regexes used in RewriteCond and RewriteRule
* with start and end characters so we don't match anything
* we aren't intending to
*
* @param string $regex
* @return string
*/
private function wrapRegex($regex){
return '^' . $regex . '$';
}
/**
* Add a RewriteCond line
*
* @param string $type
* @param string $regex
*/
private function buildRewriteCondition($type, $regex){
$string = 'RewriteCond %{' . $type . '} ' . $this->wrapRegex(preg_quote($regex));
$this->appendLineToRewrites($string);
}
/**
* Add a RewriteRule line
*
* @param string $source
* @param string $destination
*/
private function buildRewriteRule($source, $destination){
// Append ? to the destination to prevent the query string being passed through.
$string = 'RewriteRule ' . $this->wrapRegex(preg_quote($source)) . ' ' . $destination . '? ' . $this->buildRewriteFlags();
$this->appendLineToRewrites($string);
}
/**
* Return the required flags
*
* @return string
*/
private function buildRewriteFlags(){
switch($this->http301){
case false:
$response = 'R';
break;
case true:
default:
$response = 'R=301';
}
return '[' . $response . ',L,NC]';
}
}
?>