PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/blog/wp-content/plugins/w3-total-cache/lib/W3/Plugin/Minify.php

https://github.com/kennethreitz-archive/wordpress-skeleton
PHP | 1014 lines | 626 code | 155 blank | 233 comment | 119 complexity | 0d5cfa6523974bf85b0ff38f9b474d4a MD5 | raw file
  1. <?php
  2. /**
  3. * W3 Minify plugin
  4. */
  5. require_once W3TC_LIB_W3_DIR . '/Plugin.php';
  6. /**
  7. * Class W3_Plugin_Minify
  8. */
  9. class W3_Plugin_Minify extends W3_Plugin
  10. {
  11. /**
  12. * Minify reject reason
  13. *
  14. * @var string
  15. */
  16. var $minify_reject_reason = '';
  17. /**
  18. * Array of printed styles
  19. * @var array
  20. */
  21. var $printed_styles = array();
  22. /**
  23. * Array of printed scripts
  24. * @var array
  25. */
  26. var $printed_scripts = array();
  27. /**
  28. * Runs plugin
  29. */
  30. function run()
  31. {
  32. register_activation_hook(W3TC_FILE, array(
  33. &$this,
  34. 'activate'
  35. ));
  36. register_deactivation_hook(W3TC_FILE, array(
  37. &$this,
  38. 'deactivate'
  39. ));
  40. add_filter('cron_schedules', array(
  41. &$this,
  42. 'cron_schedules'
  43. ));
  44. if ($this->_config->get_boolean('minify.enabled') && $this->_config->get_string('minify.engine') == 'file') {
  45. add_action('w3_minify_cleanup', array(
  46. &$this,
  47. 'cleanup'
  48. ));
  49. }
  50. if ($this->can_minify()) {
  51. ob_start(array(
  52. &$this,
  53. 'ob_callback'
  54. ));
  55. }
  56. }
  57. /**
  58. * Returns instance
  59. *
  60. * @return W3_Plugin_Minify
  61. */
  62. function &instance()
  63. {
  64. static $instances = array();
  65. if (!isset($instances[0])) {
  66. $class = __CLASS__;
  67. $instances[0] = & new $class();
  68. }
  69. return $instances[0];
  70. }
  71. /**
  72. * Activate plugin action
  73. */
  74. function activate()
  75. {
  76. if (!is_dir(W3TC_CONTENT_MINIFY_DIR)) {
  77. if (@mkdir(W3TC_CONTENT_MINIFY_DIR, 0755)) {
  78. @chmod(W3TC_CONTENT_MINIFY_DIR, 0755);
  79. } else {
  80. w3_writable_error(W3TC_CONTENT_MINIFY_DIR);
  81. }
  82. }
  83. $file_index = W3TC_CONTENT_MINIFY_DIR . '/index.php';
  84. if (@copy(W3TC_INSTALL_MINIFY_DIR . '/index.php', $file_index)) {
  85. @chmod($file_index, 0644);
  86. } else {
  87. w3_writable_error($file_index);
  88. }
  89. if ($this->_config->get_boolean('minify.rewrite') && !$this->write_rules()) {
  90. w3_writable_error(W3TC_CONTENT_MINIFY_DIR . '/.htaccess');
  91. }
  92. $this->schedule();
  93. }
  94. /**
  95. * Deactivate plugin action
  96. */
  97. function deactivate()
  98. {
  99. $this->unschedule();
  100. @unlink(W3TC_CONTENT_MINIFY_DIR . '/index.php');
  101. $this->remove_rules();
  102. }
  103. /**
  104. * Schedules events
  105. */
  106. function schedule()
  107. {
  108. if ($this->_config->get_boolean('minify.enabled') && $this->_config->get_string('minify.engine') == 'file') {
  109. if (!wp_next_scheduled('w3_minify_cleanup')) {
  110. wp_schedule_event(time(), 'w3_minify_cleanup', 'w3_minify_cleanup');
  111. }
  112. } else {
  113. $this->unschedule();
  114. }
  115. }
  116. /**
  117. * Unschedules events
  118. */
  119. function unschedule()
  120. {
  121. if (wp_next_scheduled('w3_minify_cleanup')) {
  122. wp_clear_scheduled_hook('w3_minify_cleanup');
  123. }
  124. }
  125. /**
  126. * Does disk cache cleanup
  127. *
  128. * @return void
  129. */
  130. function cleanup()
  131. {
  132. require_once W3TC_LIB_W3_DIR . '/Cache/File/Minify/Manager.php';
  133. $w3_cache_file_minify_manager = & new W3_Cache_File_Minify_Manager(array(
  134. 'cache_dir' => W3TC_CACHE_FILE_MINIFY_DIR,
  135. 'expire' => $this->_config->get_integer('minify.lifetime')
  136. ));
  137. $w3_cache_file_minify_manager->clean();
  138. }
  139. /**
  140. * Cron schedules filter
  141. *
  142. * @paran array $schedules
  143. * @return array
  144. */
  145. function cron_schedules($schedules)
  146. {
  147. $gc = $this->_config->get_integer('minify.file.gc');
  148. return array_merge($schedules, array(
  149. 'w3_minify_cleanup' => array(
  150. 'interval' => $gc,
  151. 'display' => sprintf('Every %d seconds', $gc)
  152. )
  153. ));
  154. }
  155. /**
  156. * OB callback
  157. *
  158. * @param string $buffer
  159. * @return string
  160. */
  161. function ob_callback($buffer)
  162. {
  163. if ($buffer != '' && w3_is_xml($buffer) && $this->can_minify2()) {
  164. $head_prepend = '';
  165. $body_append = '';
  166. if ($this->_config->get_boolean('minify.css.enable') && !in_array('include', $this->printed_styles)) {
  167. $head_prepend .= $this->get_styles('include');
  168. }
  169. if ($this->_config->get_boolean('minify.js.enable')) {
  170. if (!in_array('include', $this->printed_scripts)) {
  171. $head_prepend .= $this->get_scripts('include');
  172. }
  173. if (!in_array('include-nb', $this->printed_scripts)) {
  174. $head_prepend .= $this->get_scripts('include-nb');
  175. }
  176. if (!in_array('include-footer', $this->printed_scripts)) {
  177. $body_append .= $this->get_scripts('include-footer');
  178. }
  179. if (!in_array('include-footer-nb', $this->printed_scripts)) {
  180. $body_append .= $this->get_scripts('include-footer-nb');
  181. }
  182. }
  183. if ($head_prepend != '') {
  184. $buffer = preg_replace('~<head(\s+[^<>]+)*>~Ui', '\\0' . $head_prepend, $buffer, 1);
  185. }
  186. if ($body_append != '') {
  187. $buffer = preg_replace('~<\\/body>~', $body_append . '\\0', $buffer, 1);
  188. }
  189. $buffer = $this->clean($buffer);
  190. if ($this->_config->get_boolean('minify.debug')) {
  191. $buffer .= "\r\n\r\n" . $this->get_debug_info();
  192. }
  193. }
  194. return $buffer;
  195. }
  196. /**
  197. * Cleans content
  198. *
  199. * @param string $content
  200. * @return string
  201. */
  202. function clean($content)
  203. {
  204. if (!is_feed()) {
  205. if ($this->_config->get_boolean('minify.css.enable')) {
  206. $content = $this->clean_styles($content);
  207. $content = preg_replace('~<style[^<>]*>\s*</style>~', '', $content);
  208. }
  209. if ($this->_config->get_boolean('minify.js.enable')) {
  210. $content = $this->clean_scripts($content);
  211. }
  212. }
  213. if ($this->_config->get_boolean('minify.html.enable') && !($this->_config->get_boolean('minify.html.reject.admin') && current_user_can('manage_options'))) {
  214. $content = $this->minify_html($content);
  215. }
  216. return $content;
  217. }
  218. /**
  219. * Cleans styles
  220. *
  221. * @param string $content
  222. * @return string
  223. */
  224. function clean_styles($content)
  225. {
  226. $regexps = array();
  227. $groups = $this->_config->get_array('minify.css.groups');
  228. $domain_url_regexp = w3_get_domain_url_regexp();
  229. foreach ($groups as $group => $locations) {
  230. foreach ((array) $locations as $location => $config) {
  231. if (!empty($config['files'])) {
  232. foreach ((array) $config['files'] as $file) {
  233. if (w3_is_url($file) && !preg_match('~' . $domain_url_regexp . '~i', $file)) {
  234. // external CSS files
  235. $regexps[] = w3_preg_quote($file);
  236. } else {
  237. // local CSS files
  238. $file = ltrim(preg_replace('~' . $domain_url_regexp . '~i', '', $file), '/\\');
  239. $regexps[] = '(' . $domain_url_regexp . ')?/?' . w3_preg_quote($file);
  240. }
  241. }
  242. }
  243. }
  244. }
  245. foreach ($regexps as $regexp) {
  246. $content = preg_replace('~<link\s+[^<>]*href=["\']?' . $regexp . '["\']?[^<>]*/?>~is', '', $content);
  247. $content = preg_replace('~@import\s+(url\s*)?\(?["\']?\s*' . $regexp . '\s*["\']?\)?[^;]*;?~is', '', $content);
  248. }
  249. return $content;
  250. }
  251. /**
  252. * Cleans scripts
  253. *
  254. * @param string $content
  255. * @return string
  256. */
  257. function clean_scripts($content)
  258. {
  259. $regexps = array();
  260. $groups = $this->_config->get_array('minify.js.groups');
  261. $domain_url_regexp = w3_get_domain_url_regexp();
  262. foreach ($groups as $group => $locations) {
  263. foreach ((array) $locations as $location => $config) {
  264. if (!empty($config['files'])) {
  265. foreach ((array) $config['files'] as $file) {
  266. if (w3_is_url($file) && !preg_match('~' . $domain_url_regexp . '~i', $file)) {
  267. // external JS files
  268. $regexps[] = w3_preg_quote($file);
  269. } else {
  270. // local JS files
  271. $file = ltrim(preg_replace('~' . $domain_url_regexp . '~i', '', $file), '/\\');
  272. $regexps[] = '(' . $domain_url_regexp . ')?/?' . w3_preg_quote($file);
  273. }
  274. }
  275. }
  276. }
  277. }
  278. foreach ($regexps as $regexp) {
  279. $content = preg_replace('~<script\s+[^<>]*src=["\']?' . $regexp . '["\']?[^<>]*>\s*</script>~is', '', $content);
  280. }
  281. return $content;
  282. }
  283. /**
  284. * Minifies HTML
  285. *
  286. * @param string $content
  287. * @return string
  288. */
  289. function minify_html($content)
  290. {
  291. require_once W3TC_LIB_MINIFY_DIR . '/Minify/HTML.php';
  292. require_once W3TC_LIB_MINIFY_DIR . '/Minify/CSS.php';
  293. require_once W3TC_LIB_MINIFY_DIR . '/JSMin.php';
  294. $options = array(
  295. 'xhtml' => true,
  296. 'stripCrlf' => $this->_config->get_boolean('minify.html.strip.crlf'),
  297. 'cssStripCrlf' => $this->_config->get_boolean('minify.css.strip.crlf'),
  298. 'cssStripComments' => $this->_config->get_boolean('minify.css.strip.comments'),
  299. 'jsStripCrlf' => $this->_config->get_boolean('minify.js.strip.crlf'),
  300. 'jsStripComments' => $this->_config->get_boolean('minify.js.strip.comments')
  301. );
  302. if ($this->_config->get_boolean('minify.html.inline.css')) {
  303. $options['cssMinifier'] = array(
  304. 'Minify_CSS',
  305. 'minify'
  306. );
  307. }
  308. if ($this->_config->get_boolean('minify.html.inline.js')) {
  309. $options['jsMinifier'] = array(
  310. 'JSMin',
  311. 'minify'
  312. );
  313. }
  314. try {
  315. $content = Minify_HTML::minify($content, $options);
  316. } catch (Exception $exception) {
  317. return sprintf('<strong>W3 Total Cache Error:</strong> Minify error: %s', $exception->getMessage());
  318. }
  319. return $content;
  320. }
  321. /**
  322. * Returns current group
  323. *
  324. * @return string
  325. */
  326. function get_group()
  327. {
  328. static $group = null;
  329. if ($group === null) {
  330. switch (true) {
  331. case (is_404() && ($template = get_404_template())):
  332. case (is_search() && ($template = get_search_template())):
  333. case (is_tax() && ($template = get_taxonomy_template())):
  334. case (is_home() && ($template = get_home_template())):
  335. case (is_attachment() && ($template = get_attachment_template())):
  336. case (is_single() && ($template = get_single_template())):
  337. case (is_page() && ($template = get_page_template())):
  338. case (is_category() && ($template = get_category_template())):
  339. case (is_tag() && ($template = get_tag_template())):
  340. case (is_author() && ($template = get_author_template())):
  341. case (is_date() && ($template = get_date_template())):
  342. case (is_archive() && ($template = get_archive_template())):
  343. case (is_comments_popup() && ($template = get_comments_popup_template())):
  344. case (is_paged() && ($template = get_paged_template())):
  345. $group = basename($template, '.php');
  346. break;
  347. default:
  348. $group = 'default';
  349. break;
  350. }
  351. }
  352. return $group;
  353. }
  354. /**
  355. * Returns style link
  356. *
  357. * @param string $url
  358. * @param string $import
  359. */
  360. function get_style($url, $import = false)
  361. {
  362. if ($import) {
  363. return "<style type=\"text/css\" media=\"all\">@import url(\"" . $url . "\");</style>\r\n";
  364. } else {
  365. return "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . str_replace('&', '&amp;', $url) . "\" media=\"all\" />\r\n";
  366. }
  367. }
  368. /**
  369. * Prints script link
  370. *
  371. * @param string $url
  372. * @param boolean $non_blocking
  373. */
  374. function get_script($url, $blocking = true)
  375. {
  376. static $non_blocking_function = false;
  377. if ($blocking) {
  378. return '<script type="text/javascript" src="' . str_replace('&', '&amp;', $url) . '"></script>';
  379. } else {
  380. $script = '';
  381. if (!$non_blocking_function) {
  382. $non_blocking_function = true;
  383. $script = "<script type=\"text/javascript\">function w3tc_load_js(u){var d=document,p=d.getElementsByTagName('HEAD')[0],c=d.createElement('script');c.type='text/javascript';c.src=u;p.appendChild(c);}</script>";
  384. }
  385. $script .= "<script type=\"text/javascript\">w3tc_load_js('" . $url . "');</script>";
  386. return $script;
  387. }
  388. }
  389. /**
  390. * Returns style link for styles group
  391. *
  392. * @param string $location
  393. * @param string $group
  394. */
  395. function get_styles($location, $group = null)
  396. {
  397. $styles = '';
  398. $groups = $this->_config->get_array('minify.css.groups');
  399. if (empty($group)) {
  400. $group = $this->get_group();
  401. }
  402. if ($group != 'default' && empty($groups[$group][$location]['files'])) {
  403. $group = 'default';
  404. }
  405. if (!empty($groups[$group][$location]['files'])) {
  406. $styles .= $this->get_style($this->format_url($group, $location, 'css'), isset($groups[$group][$location]['import']) ? (boolean) $groups[$group][$location]['import'] : false);
  407. }
  408. return $styles;
  409. }
  410. /**
  411. * Returns script linkg for scripts group
  412. *
  413. * @param string $location
  414. * @param string $group
  415. */
  416. function get_scripts($location, $group = null)
  417. {
  418. $scripts = '';
  419. $groups = $this->_config->get_array('minify.js.groups');
  420. if (empty($group)) {
  421. $group = $this->get_group();
  422. }
  423. if ($group != 'default' && empty($groups[$group][$location]['files'])) {
  424. $group = 'default';
  425. }
  426. if (!empty($groups[$group][$location]['files'])) {
  427. $scripts .= $this->get_script($this->format_url($group, $location, 'js'), isset($groups[$group][$location]['blocking']) ? (boolean) $groups[$group][$location]['blocking'] : true);
  428. }
  429. return $scripts;
  430. }
  431. /**
  432. * Returns link for custom script files
  433. *
  434. * @param string|array $files
  435. * @param boolean $blocking
  436. */
  437. function get_custom_script($files, $blocking = true)
  438. {
  439. return $this->get_script($this->format_custom_url($files), $blocking);
  440. }
  441. /**
  442. * Returns link for custom style files
  443. *
  444. * @param string|array $files
  445. * @param boolean $import
  446. */
  447. function get_custom_style($files, $import = false)
  448. {
  449. return $this->get_style($this->format_custom_url($files), $import);
  450. }
  451. /**
  452. * Formats URL
  453. *
  454. * @param string $group
  455. * @param string $location
  456. * @param string $type
  457. * @return string
  458. */
  459. function format_url($group, $location, $type)
  460. {
  461. $site_url_ssl = w3_get_site_url_ssl();
  462. if ($this->_config->get_boolean('minify.rewrite')) {
  463. return sprintf('%s/%s/%s.%s.%s', $site_url_ssl, W3TC_CONTENT_MINIFY_DIR_NAME, $group, $location, $type);
  464. }
  465. return sprintf('%s/%s/index.php?gg=%s&g=%s&t=%s', $site_url_ssl, W3TC_CONTENT_MINIFY_DIR_NAME, $group, $location, $type);
  466. }
  467. /**
  468. * Formats custom URL
  469. *
  470. * @param string|array $files
  471. * @return string
  472. */
  473. function format_custom_url($files)
  474. {
  475. if (!is_array($files)) {
  476. $files = array(
  477. (string) $files
  478. );
  479. }
  480. $base = false;
  481. foreach ($files as &$file) {
  482. $current_base = dirname($file);
  483. if ($base && $base != $current_base) {
  484. $base = false;
  485. break;
  486. } else {
  487. $file = basename($file);
  488. $base = $current_base;
  489. }
  490. }
  491. $site_url_ssl = w3_get_site_url_ssl();
  492. $url = sprintf('%s/%s/minify.php?f=%s', $site_url_ssl, W3TC_CONTENT_DIR_NAME, implode(',', $files));
  493. if ($base) {
  494. $url .= sprintf('&b=%s', $base);
  495. }
  496. return $url;
  497. }
  498. /**
  499. * Returns array of minify URLs
  500. *
  501. * @return array
  502. */
  503. function get_urls()
  504. {
  505. $files = array();
  506. $js_groups = $this->_config->get_array('minify.js.groups');
  507. $css_groups = $this->_config->get_array('minify.css.groups');
  508. foreach ($js_groups as $js_group => $js_locations) {
  509. foreach ((array) $js_locations as $js_location => $js_config) {
  510. if (!empty($js_config['files'])) {
  511. $files[] = $this->format_url($js_group, $js_location, 'js');
  512. }
  513. }
  514. }
  515. foreach ($css_groups as $css_group => $css_locations) {
  516. foreach ((array) $css_locations as $css_location => $css_config) {
  517. if (!empty($css_config['files'])) {
  518. $files[] = $this->format_url($css_group, $css_location, 'css');
  519. }
  520. }
  521. }
  522. return $files;
  523. }
  524. /**
  525. * Returns debug info
  526. */
  527. function get_debug_info()
  528. {
  529. $group = $this->get_group();
  530. $debug_info = "<!-- W3 Total Cache: Minify debug info:\r\n";
  531. $debug_info .= sprintf("%s%s\r\n", str_pad('Engine: ', 20), w3_get_engine_name($this->_config->get_string('minify.engine')));
  532. $debug_info .= sprintf("%s%s\r\n", str_pad('Group: ', 20), $group);
  533. require_once W3TC_LIB_W3_DIR . '/Minify.php';
  534. $w3_minify = & W3_Minify::instance();
  535. $css_groups = $w3_minify->get_groups($group, 'css');
  536. if (count($css_groups)) {
  537. $debug_info .= "Stylesheet info:\r\n";
  538. $debug_info .= sprintf("%s | %s | % s | %s\r\n", str_pad('Location', 15, ' ', STR_PAD_BOTH), str_pad('Last modified', 19, ' ', STR_PAD_BOTH), str_pad('Size', 12, ' ', STR_PAD_LEFT), 'Path');
  539. foreach ($css_groups as $css_group => $css_files) {
  540. foreach ($css_files as $css_file => $css_file_path) {
  541. if (is_a($css_file_path, 'Minify_Source')) {
  542. $css_file_path = $css_file_path->filepath;
  543. $css_file_info = sprintf('%s (%s)', $css_file, $css_file_path);
  544. } else {
  545. $css_file_info = $css_file;
  546. $css_file_path = ABSPATH . ltrim($css_file_path, '/\\');
  547. }
  548. $debug_info .= sprintf("%s | %s | % s | %s\r\n", str_pad($css_group, 15, ' ', STR_PAD_BOTH), str_pad(date('Y-m-d H:i:s', filemtime($css_file_path)), 19, ' ', STR_PAD_BOTH), str_pad(filesize($css_file_path), 12, ' ', STR_PAD_LEFT), $css_file_info);
  549. }
  550. }
  551. }
  552. $js_groups = $w3_minify->get_groups($group, 'js');
  553. if (count($js_groups)) {
  554. $debug_info .= "JavaScript info:\r\n";
  555. $debug_info .= sprintf("%s | %s | % s | %s\r\n", str_pad('Location', 15, ' ', STR_PAD_BOTH), str_pad('Last modified', 19, ' ', STR_PAD_BOTH), str_pad('Size', 12, ' ', STR_PAD_LEFT), 'Path');
  556. foreach ($js_groups as $js_group => $js_files) {
  557. foreach ($js_files as $js_file => $js_file_path) {
  558. if (is_a($js_file_path, 'Minify_Source')) {
  559. $js_file_path = $js_file_path->filepath;
  560. $js_file_info = sprintf('%s (%s)', $js_file, $js_file_path);
  561. } else {
  562. $js_file_path = $js_file_info = ABSPATH . ltrim($js_file, '/\\');
  563. }
  564. $debug_info .= sprintf("%s | %s | % s | %s\r\n", str_pad($js_group, 15, ' ', STR_PAD_BOTH), str_pad(date('Y-m-d H:i:s', filemtime($js_file_path)), 19, ' ', STR_PAD_BOTH), str_pad(filesize($js_file_path), 12, ' ', STR_PAD_LEFT), $js_file_info);
  565. }
  566. }
  567. }
  568. $debug_info .= '-->';
  569. return $debug_info;
  570. }
  571. /**
  572. * Check if we can do minify logic
  573. *
  574. * @return boolean
  575. */
  576. function can_minify()
  577. {
  578. /**
  579. * Skip if Minify is disabled
  580. */
  581. if (!$this->_config->get_boolean('minify.enabled')) {
  582. $this->minify_reject_reason = 'minify is disabled';
  583. return false;
  584. }
  585. /**
  586. * Skip if Admin
  587. */
  588. if (defined('WP_ADMIN')) {
  589. $this->minify_reject_reason = 'wp-admin';
  590. return false;
  591. }
  592. /**
  593. * Skip if doint AJAX
  594. */
  595. if (defined('DOING_AJAX')) {
  596. $this->minify_reject_reason = 'doing AJAX';
  597. return false;
  598. }
  599. /**
  600. * Skip if doing cron
  601. */
  602. if (defined('DOING_CRON')) {
  603. $this->minify_reject_reason = 'doing cron';
  604. return false;
  605. }
  606. /**
  607. * Skip if APP request
  608. */
  609. if (defined('APP_REQUEST')) {
  610. $this->minify_reject_reason = 'application request';
  611. return false;
  612. }
  613. /**
  614. * Skip if XMLRPC request
  615. */
  616. if (defined('XMLRPC_REQUEST')) {
  617. $this->minify_reject_reason = 'XMLRPC request';
  618. return false;
  619. }
  620. /**
  621. * Check User agent
  622. */
  623. if (!$this->check_ua()) {
  624. $this->minify_reject_reason = 'user agent is rejected';
  625. return false;
  626. }
  627. /**
  628. * Check request URI
  629. */
  630. if (!$this->check_request_uri()) {
  631. $this->minify_reject_reason = 'request URI is rejected';
  632. return false;
  633. }
  634. return true;
  635. }
  636. /**
  637. * Check if we can do minify logic
  638. *
  639. * @return boolean
  640. */
  641. function can_minify2()
  642. {
  643. if ($this->_config->get_boolean('minify.html.reject.feed') && function_exists('is_feed') && is_feed()) {
  644. $this->minify_reject_reason = 'feed is rejected';
  645. return false;
  646. }
  647. return true;
  648. }
  649. /**
  650. * Checks User Agent
  651. *
  652. * @return boolean
  653. */
  654. function check_ua()
  655. {
  656. foreach ($this->_config->get_array('minify.reject.ua') as $ua) {
  657. if (stristr($_SERVER['HTTP_USER_AGENT'], $ua) !== false) {
  658. return false;
  659. }
  660. }
  661. return true;
  662. }
  663. /**
  664. * Checks request URI
  665. *
  666. * @return boolean
  667. */
  668. function check_request_uri()
  669. {
  670. $auto_reject_uri = array(
  671. 'wp-login',
  672. 'wp-register'
  673. );
  674. foreach ($auto_reject_uri as $uri) {
  675. if (strstr($_SERVER['REQUEST_URI'], $uri) !== false) {
  676. return false;
  677. }
  678. }
  679. foreach ($this->_config->get_array('minify.reject.uri') as $expr) {
  680. $expr = trim($expr);
  681. if ($expr != '' && preg_match('@' . $expr . '@i', $_SERVER['REQUEST_URI'])) {
  682. return false;
  683. }
  684. }
  685. return true;
  686. }
  687. /**
  688. * Generates rules
  689. *
  690. * @return string
  691. */
  692. function generate_rules()
  693. {
  694. $compressions = array();
  695. $engine = $this->_config->get_string('minify.engine');
  696. $lifetime = $this->_config->get_integer('minify.lifetime');
  697. $rules = '';
  698. $rules .= "# BEGIN W3TC Minify\n";
  699. if ($engine == 'file') {
  700. $compression = $this->_config->get_string('minify.compression');
  701. if ($compression != '') {
  702. if (stristr($compression, 'gzip') !== false) {
  703. $compressions[] = 'gzip';
  704. }
  705. if (stristr($compression, 'deflate') !== false) {
  706. $compressions[] = 'deflate';
  707. }
  708. }
  709. if (count($compressions)) {
  710. $rules .= "<IfModule mod_mime.c>\n";
  711. foreach ($compressions as $_compression) {
  712. $rules .= " AddEncoding " . $_compression . " ." . $_compression . "\n";
  713. $rules .= " <Files *.css." . $_compression . ">\n";
  714. $rules .= " ForceType text/css\n";
  715. $rules .= " </Files>\n";
  716. $rules .= " <Files *.js." . $_compression . ">\n";
  717. $rules .= " ForceType application/x-javascript\n";
  718. $rules .= " </Files>\n";
  719. }
  720. $rules .= "</IfModule>\n";
  721. $rules .= "<IfModule mod_setenvif.c>\n";
  722. $rules .= " SetEnvIfNoCase Accept-Encoding (" . implode('|', $compressions) . ") APPEND_EXT=.$1\n";
  723. $rules .= " <IfModule mod_deflate.c>\n";
  724. $rules .= " SetEnvIfNoCase Request_URI \\.(" . implode('|', $compressions) . ")$ no-gzip\n";
  725. $rules .= " </IfModule>\n";
  726. $rules .= "</IfModule>\n";
  727. }
  728. $rules .= "<IfModule mod_expires.c>\n";
  729. $rules .= " ExpiresActive On\n";
  730. $rules .= " ExpiresByType text/css M" . $lifetime . "\n";
  731. $rules .= " ExpiresByType application/x-javascript M" . $lifetime . "\n";
  732. $rules .= "</IfModule>\n";
  733. $rules .= "<IfModule mod_headers.c>\n";
  734. $rules .= " Header set Pragma public\n";
  735. $rules .= " Header set X-Powered-By \"" . W3TC_POWERED_BY . "\"\n";
  736. $rules .= " Header set Vary \"Accept-Encoding\"\n";
  737. $rules .= " Header append Cache-Control \"public, must-revalidate, proxy-revalidate\"\n";
  738. $rules .= "</IfModule>\n";
  739. }
  740. $rules .= "<IfModule mod_rewrite.c>\n";
  741. $rules .= " RewriteEngine On\n";
  742. if ($engine == 'file') {
  743. $rules .= " RewriteCond %{REQUEST_FILENAME}%{ENV:APPEND_EXT} -f\n";
  744. $rules .= " RewriteRule (.*) $1%{ENV:APPEND_EXT} [L]\n";
  745. }
  746. $rules .= " RewriteRule ^([a-z0-9\\-_]+)\\.(include(-footer)?(-nb)?)\\.(css|js)$ index.php?gg=$1&g=$2&t=$5 [L]\n";
  747. $rules .= "</IfModule>\n";
  748. $rules .= "# END W3TC Minify\n\n";
  749. return $rules;
  750. }
  751. /**
  752. * Writes rules to file cache .htaccess
  753. *
  754. * @return boolean
  755. */
  756. function write_rules()
  757. {
  758. $path = W3TC_CONTENT_MINIFY_DIR . '/.htaccess';
  759. if (file_exists($path)) {
  760. if (($data = @file_get_contents($path)) !== false) {
  761. $data = $this->erase_rules($data);
  762. } else {
  763. return false;
  764. }
  765. } else {
  766. $data = '';
  767. }
  768. $data = trim($this->generate_rules() . $data);
  769. return @file_put_contents($path, $data);
  770. }
  771. /**
  772. * Erases W3TC rules from config
  773. *
  774. * @param string $data
  775. * @return string
  776. */
  777. function erase_rules($data)
  778. {
  779. $data = preg_replace('~# BEGIN W3TC Minify.*# END W3TC Minify~Us', '', $data);
  780. $data = trim($data);
  781. return $data;
  782. }
  783. /**
  784. * Removes W3TC rules from file cache dir
  785. *
  786. * @return boolean
  787. */
  788. function remove_rules()
  789. {
  790. $path = W3TC_CONTENT_MINIFY_DIR . '/.htaccess';
  791. return @unlink($path);
  792. }
  793. /**
  794. * Checks rules
  795. *
  796. * @return boolean
  797. */
  798. function check_rules()
  799. {
  800. $path = W3TC_CACHE_FILE_MINIFY_DIR . '/.htaccess';
  801. $search = $this->generate_rules();
  802. return (($data = @file_get_contents($path)) && strstr(w3_clean_rules($data), w3_clean_rules($search)) !== false);
  803. }
  804. }
  805. /**
  806. * Prints script link for scripts group
  807. *
  808. * @param string $location
  809. * @param string $group
  810. */
  811. function w3tc_scripts($location, $group = null)
  812. {
  813. $w3_plugin_minify = & W3_Plugin_Minify::instance();
  814. $w3_plugin_minify->printed_scripts[] = $location;
  815. echo $w3_plugin_minify->get_scripts($location, $group);
  816. }
  817. /**
  818. * Prints style link for styles group
  819. *
  820. * @param string $location
  821. * @param string $group
  822. */
  823. function w3tc_styles($location, $group = null)
  824. {
  825. $w3_plugin_minify = & W3_Plugin_Minify::instance();
  826. $w3_plugin_minify->printed_styles[] = $location;
  827. echo $w3_plugin_minify->get_styles($location, $group);
  828. }
  829. /**
  830. * Prints link for custom scripts
  831. *
  832. * @param string|array $files
  833. * @param boolean $blocking
  834. */
  835. function w3tc_custom_script($files, $blocking = true)
  836. {
  837. $w3_plugin_minify = & W3_Plugin_Minify::instance();
  838. echo $w3_plugin_minify->get_custom_script($files, $blocking);
  839. }
  840. /**
  841. * Prints link for custom styles
  842. *
  843. * @param string|array $files
  844. * @param boolean $import
  845. */
  846. function w3tc_custom_style($files, $import = false)
  847. {
  848. $w3_plugin_minify = & W3_Plugin_Minify::instance();
  849. echo $w3_plugin_minify->get_custom_style($files, $import);
  850. }