| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -if (!defined('WPO_VERSION')) die('No direct access allowed'); | |
| 3 | +if (!defined('ABSPATH')) die('No direct access allowed'); | |
| 4 | 4 | |
| 5 | 5 | class WP_Optimize_Htaccess { |
| 6 | 6 | |
| 7 | 7 | /** |
| @@ -8,9 +8,9 @@ | ||
| 8 | 8 | * Full path to .htaccess file. |
| 9 | 9 | * |
| 10 | 10 | * @var string |
| 11 | 11 | */ |
| 12 | - private $_htaccess_file = ''; | |
| 12 | + private $_htaccess_file; | |
| 13 | 13 | |
| 14 | 14 | /** |
| 15 | 15 | * Structured content of .htaccess file. |
| 16 | 16 | * |
| @@ -47,9 +47,9 @@ | ||
| 47 | 47 | return is_file($this->_htaccess_file); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | /** |
| 51 | - * Checks if .htaccess file is readaable. | |
| 51 | + * Checks if .htaccess file is readable. | |
| 52 | 52 | * |
| 53 | 53 | * @return bool |
| 54 | 54 | */ |
| 55 | 55 | public function is_readable() { |
| @@ -61,9 +61,9 @@ | ||
| 61 | 61 | * |
| 62 | 62 | * @return bool |
| 63 | 63 | */ |
| 64 | 64 | public function is_writable() { |
| 65 | - return is_writable($this->_htaccess_file); | |
| 65 | + return wp_is_writable($this->_htaccess_file); | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | /** |
| 69 | 69 | * Read content of .htaccess file and store it as a tree in $_file_tree variable. |
| @@ -77,14 +77,15 @@ | ||
| 77 | 77 | * [4] => 'RewriteCond %{REQUEST_FILENAME} !-f', |
| 78 | 78 | * [5] => 'RewriteCond %{REQUEST_FILENAME} !-d', |
| 79 | 79 | * [6] => 'RewriteRule . /index.php [L]', |
| 80 | 80 | * [7] => '</IfModule>', |
| 81 | + * ] | |
| 81 | 82 | * [2] => '# END WordPress' |
| 82 | 83 | * |
| 83 | 84 | * @return void |
| 84 | 85 | */ |
| 85 | 86 | public function read_file() { |
| 86 | - if (false == $this->is_exists() || false == $this->is_readable()) return; | |
| 87 | + if (!$this->is_exists() || !$this->is_readable()) return; | |
| 87 | 88 | |
| 88 | 89 | $content = file_get_contents($this->_htaccess_file); |
| 89 | 90 | |
| 90 | 91 | $content = explode("\n", $content); |
| @@ -130,15 +131,50 @@ | ||
| 130 | 131 | /** |
| 131 | 132 | * Write current $_file_tree content into .htaccess file. |
| 132 | 133 | */ |
| 133 | 134 | public function write_file() { |
| 134 | - $content = implode(PHP_EOL, $this->get_flat_array($this->_file_tree)); | |
| 135 | 135 | if ($this->is_writable()) { |
| 136 | - @file_put_contents($this->_htaccess_file, $content); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Hosts like WP Engine restricts use of `.htaccess` file | |
| 136 | + @file_put_contents($this->_htaccess_file, $this->get_content()); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Hosts like WP Engine restricts use of `.htaccess` file | |
| 137 | 137 | } |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | 140 | /** |
| 141 | + * Get .htaccess content as a string. | |
| 142 | + * | |
| 143 | + * @return string | |
| 144 | + */ | |
| 145 | + public function get_content() { | |
| 146 | + return implode(PHP_EOL, $this->get_flat_array($this->_file_tree)); | |
| 147 | + } | |
| 148 | + | |
| 149 | + /** | |
| 150 | + * Returns section content as a string | |
| 151 | + * | |
| 152 | + * @param string $section | |
| 153 | + * @return string | |
| 154 | + */ | |
| 155 | + public function get_section_content($section = 'WP-Optimize Browser Cache') { | |
| 156 | + $section_index = $this->search_commented_section($section); | |
| 157 | + | |
| 158 | + if (false === $section_index) return ''; | |
| 159 | + | |
| 160 | + $section_length = (false === $section_index['end']) ? null : ($section_index['end'] - $section_index['begin'] + 1); | |
| 161 | + $section_array = array_slice($this->_file_tree, $section_index['begin'], $section_length); | |
| 162 | + | |
| 163 | + return implode(PHP_EOL, $this->get_flat_array($section_array)); | |
| 164 | + } | |
| 165 | + | |
| 166 | + /** | |
| 167 | + * Recursive function that builds a flat array from a tree-structured .htaccess file array. | |
| 168 | + * Get .htaccess hash | |
| 169 | + * | |
| 170 | + * @return string | |
| 171 | + */ | |
| 172 | + public function get_hash() { | |
| 173 | + return hash('sha256', serialize($this->_file_tree)); | |
| 174 | + } | |
| 175 | + | |
| 176 | + /** | |
| 141 | 177 | * Recursive function used to prepare data for output - build flat array from $_file_tree. |
| 142 | 178 | * |
| 143 | 179 | * @param array $array |
| 144 | 180 | * @param string $prefix |
| @@ -164,13 +200,13 @@ | ||
| 164 | 200 | end($flat_array); |
| 165 | 201 | $last = key($flat_array); |
| 166 | 202 | |
| 167 | 203 | foreach ($flat_array as $key => $value) { |
| 168 | - if ('' != $value && '#' == $value[0]) { | |
| 204 | + if ('' !== $value && '#' === $value[0]) { | |
| 169 | 205 | // never add prefix for comment lines. |
| 170 | 206 | $flat_array[$key] = $value; |
| 171 | 207 | } else { |
| 172 | - $flat_array[$key] = ($key == $first || $key == $last) ? $value : $prefix . $value; | |
| 208 | + $flat_array[$key] = ($key === $first || $key === $last) ? $value : $prefix . $value; | |
| 173 | 209 | } |
| 174 | 210 | } |
| 175 | 211 | |
| 176 | 212 | return $flat_array; |
| @@ -183,10 +219,11 @@ | ||
| 183 | 219 | * # END WP-Optimize Browser Cache |
| 184 | 220 | * |
| 185 | 221 | * @param array $content |
| 186 | 222 | * @param string $section |
| 223 | + * @param bool $prepend | |
| 187 | 224 | */ |
| 188 | - public function update_commented_section($content, $section = 'WP-Optimize Browser Cache') { | |
| 225 | + public function update_commented_section($content, $section = 'WP-Optimize Browser Cache', $prepend = false) { | |
| 189 | 226 | $section_begin = $this->get_section_begin_comment($section); |
| 190 | 227 | $section_end = $this->get_section_end_comment($section); |
| 191 | 228 | |
| 192 | 229 | // add begin-end section comments. |
| @@ -197,9 +234,9 @@ | ||
| 197 | 234 | |
| 198 | 235 | // check if section with cache settings already in the file. |
| 199 | 236 | if (false === $section_index) { |
| 200 | 237 | // no section in file then add it to the end of file. |
| 201 | - $this->_file_tree = array_merge($this->_file_tree, $content); | |
| 238 | + $this->_file_tree = $prepend ? array_merge($content, $this->_file_tree) : array_merge($this->_file_tree, $content); | |
| 202 | 239 | } else { |
| 203 | 240 | $remove_length = (false === $section_index['end']) ? null : ($section_index['end'] - $section_index['begin'] + 1); |
| 204 | 241 | array_splice($this->_file_tree, $section_index['begin'], $remove_length, $content); |
| 205 | 242 | } |
| @@ -239,9 +276,9 @@ | ||
| 239 | 276 | */ |
| 240 | 277 | public function is_commented_section_exists($section = 'WP-Optimize Browser Cache') { |
| 241 | 278 | $search = $this->search_commented_section($section); |
| 242 | 279 | |
| 243 | - return (false === $search) ? false : true; | |
| 280 | + return false !== $search; | |
| 244 | 281 | } |
| 245 | 282 | |
| 246 | 283 | /** |
| 247 | 284 | * Search section in $_file_tree array wrapped by begin and end comments. |
| @@ -263,13 +300,13 @@ | ||
| 263 | 300 | if (is_array($value)) continue; |
| 264 | 301 | |
| 265 | 302 | $value = $this->normalize_string($value); |
| 266 | 303 | |
| 267 | - if ($value == $section_begin_normalized) $section_begin_index = $i; | |
| 268 | - if ($value == $section_end_normalized) $section_end_index = $i; | |
| 304 | + if ($value === $section_begin_normalized) $section_begin_index = $i; | |
| 305 | + if ($value === $section_end_normalized) $section_end_index = $i; | |
| 269 | 306 | } |
| 270 | 307 | |
| 271 | - if (false == $section_begin_index) { | |
| 308 | + if (false === $section_begin_index) { | |
| 272 | 309 | return false; |
| 273 | 310 | } else { |
| 274 | 311 | return array( |
| 275 | 312 | 'begin' => $section_begin_index, |
| @@ -323,11 +360,12 @@ | ||
| 323 | 360 | |
| 324 | 361 | $home = set_url_scheme(get_option('home'), 'http'); |
| 325 | 362 | $siteurl = set_url_scheme(get_option('siteurl'), 'http'); |
| 326 | 363 | if (!empty($home) && 0 !== strcasecmp($home, $siteurl)) { |
| 364 | + $script_filename = isset($_SERVER['SCRIPT_FILENAME']) ? sanitize_text_field(wp_unslash($_SERVER['SCRIPT_FILENAME'])) : ''; | |
| 327 | 365 | $wp_path_rel_to_home = str_ireplace($home, '', $siteurl); /* $siteurl - $home */ |
| 328 | - $pos = strripos(str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']), trailingslashit($wp_path_rel_to_home)); | |
| 329 | - $home_path = substr($_SERVER['SCRIPT_FILENAME'], 0, $pos); | |
| 366 | + $pos = strripos(str_replace('\\', '/', $script_filename), trailingslashit($wp_path_rel_to_home)); | |
| 367 | + $home_path = substr($script_filename, 0, $pos); | |
| 330 | 368 | $home_path = trailingslashit($home_path); |
| 331 | 369 | } else { |
| 332 | 370 | $home_path = ABSPATH; |
| 333 | 371 | } |