PageRenderTime 32ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/web/app/plugins/w3-total-cache/ConfigCompiler.php

https://bitbucket.org/wi-labs/dbef
PHP | 484 lines | 335 code | 88 blank | 61 comment | 78 complexity | 41aebcd23d98329f9dccd30b25cc944a MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, MIT, LGPL-3.0, BSD-3-Clause, 0BSD
  1. <?php
  2. namespace W3TC;
  3. class ConfigCompiler {
  4. private $_blog_id;
  5. private $_preview;
  6. private $_data;
  7. private $_keys;
  8. /**
  9. * Returns true is key is not modifiable anymore
  10. * Placed here to limit class loading
  11. *
  12. * @return bool
  13. */
  14. static public function child_key_sealed( $key, $master_data, $child_data ) {
  15. if ( isset( $master_data['common.force_master'] ) &&
  16. (boolean)$master_data['common.force_master'] )
  17. return true;
  18. // affects rules which are global, not possible to overload
  19. if ( $key == 'pgcache.engine' &&
  20. ( $master_data['pgcache.engine'] == 'file_generic' ) )
  21. return true;
  22. if ( in_array( $key, array(
  23. 'minify.rewrite',
  24. 'browsercache.rewrite',
  25. 'version' ) ) )
  26. return true;
  27. include W3TC_DIR . '/ConfigKeys.php';
  28. // key which marks overloads is always editable
  29. $overloads_postfix = '.configuration_overloaded';
  30. // extension settings sealing
  31. // e.g. array('newrelic' , '...') is controlled
  32. // by 'newrelic.configuration_overloaded']
  33. $block_key = ( is_array( $key ) ? $key[0] : $key );
  34. if ( isset( $child_data[$block_key] ) &&
  35. isset( $child_data[$block_key . $overloads_postfix] ) &&
  36. (boolean)$child_data[$block_key . $overloads_postfix] )
  37. return false;
  38. if ( !is_array( $key ) ) {
  39. if ( substr( $key, strlen( $key ) - strlen( $overloads_postfix ),
  40. strlen( $overloads_postfix ) ) == $overloads_postfix )
  41. return false;
  42. // default sealing
  43. foreach ( $overloading_keys_scope as $i ) {
  44. $overloading_key = $i['key'];
  45. // check if this key is allowed by overloading-mark key
  46. if ( substr( $key, 0, strlen( $i['prefix'] ) ) == $i['prefix'] ) {
  47. if ( !isset( $child_data[$overloading_key] ) )
  48. return true;
  49. if ( (boolean)$child_data[$overloading_key] )
  50. return false;
  51. }
  52. }
  53. }
  54. return true;
  55. }
  56. /**
  57. * Reads config from file and returns it's content as array (or null)
  58. * Stored in this class to limit class loading
  59. */
  60. static private function util_array_from_file_legacy_v2( $filename ) {
  61. if ( file_exists( $filename ) && is_readable( $filename ) ) {
  62. // including file directly instead of read+eval causes constant
  63. // problems with APC, ZendCache, and WSOD in a case of
  64. // broken config file
  65. $content = @file_get_contents( $filename );
  66. $config = @json_decode( $content, true );
  67. if ( is_array( $config ) )
  68. return $config;
  69. }
  70. return null;
  71. }
  72. public function __construct( $blog_id, $preview ) {
  73. $this->_blog_id = $blog_id;
  74. $this->_preview = $preview;
  75. include W3TC_DIR . '/ConfigKeys.php';
  76. $this->_keys = $keys;
  77. // move _date to initial state
  78. foreach ( $this->_keys as $key => $value )
  79. $this->_data[$key] = $value['default'];
  80. $this->_data['version'] = W3TC_VERSION;
  81. $this->set_dynamic_defaults();
  82. }
  83. public function load( $data = null ) {
  84. // apply data from master config
  85. if ( is_null( $data ) ) {
  86. $data = Config::util_array_from_storage( 0, $this->_preview );
  87. }
  88. if ( is_null( $data ) && $this->_preview ) {
  89. // try to read production data when preview not available
  90. $data = Config::util_array_from_storage( 0, false );
  91. }
  92. // try to get legacy v2 data
  93. if ( is_null( $data ) ) {
  94. $master_filename = Config::util_config_filename_legacy_v2( 0,
  95. $this->_preview );
  96. $data = self::util_array_from_file_legacy_v2( $master_filename );
  97. }
  98. if ( is_array( $data ) ) {
  99. $data = $this->upgrade( $data );
  100. foreach ( $data as $key => $value )
  101. $this->_data[$key] = $value;
  102. }
  103. if ( $this->is_master() )
  104. return;
  105. // apply child config
  106. $data = Config::util_array_from_storage( $this->_blog_id,
  107. $this->_preview );
  108. if ( is_null( $data ) && $this->_preview ) {
  109. // try to read production data when preview not available
  110. $data = Config::util_array_from_storage( $this->_blog_id,
  111. false );
  112. }
  113. // try to get legacy v2 data
  114. if ( is_null( $data ) ) {
  115. $child_filename = Config::util_config_filename_legacy_v2(
  116. $this->_blog_id, $this->_preview );
  117. $data = self::util_array_from_file_legacy_v2( $child_filename );
  118. }
  119. if ( is_array( $data ) ) {
  120. $data = $this->upgrade( $data );
  121. foreach ( $data as $key => $value ) {
  122. if ( !ConfigCompiler::child_key_sealed( $key, $this->_data, $data ) )
  123. $this->_data[$key] = $value;
  124. }
  125. }
  126. }
  127. public function apply_data( $data ) {
  128. foreach ( $data as $key => $value )
  129. $this->_data[$key] = $value;
  130. }
  131. public function get_data() {
  132. return $this->_data;
  133. }
  134. public function save() {
  135. $data = array(
  136. 'version' => $this->_data['version']
  137. );
  138. if ( $this->is_master() ) {
  139. foreach ( $this->_data as $key => $value )
  140. $data[$key] = $this->_data[$key];
  141. } else {
  142. // write only overwrited keys
  143. $master = new ConfigCompiler( 0, $this->_preview );
  144. $master->load();
  145. foreach ( $this->_data as $key => $value ) {
  146. if ( !ConfigCompiler::child_key_sealed( $key, $master->_data,
  147. $this->_data ) )
  148. $data[$key] = $this->_data[$key];
  149. }
  150. }
  151. ConfigUtil::save_item( $this->_blog_id, $this->_preview, $data );
  152. }
  153. /**
  154. * Returns true if we edit master config
  155. *
  156. * @return boolean
  157. */
  158. private function is_master() {
  159. return $this->_blog_id <= 0;
  160. }
  161. private function set_dynamic_defaults() {
  162. if ( empty( $this->_data['stats.access_log.webserver'] ) ) {
  163. if ( Util_Environment::is_nginx() ) {
  164. $this->_data['stats.access_log.webserver'] = 'nginx';
  165. $this->_data['stats.access_log.format'] = '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
  166. } else {
  167. $this->_data['stats.access_log.webserver'] = 'apache';
  168. }
  169. }
  170. }
  171. /**
  172. * Apply new default values when version changes
  173. */
  174. private function upgrade( $file_data ) {
  175. if ( !isset( $file_data['version'] ) ) {
  176. $file_data['version'] = '0.0.0';
  177. }
  178. if ( !function_exists( 'bb2_start' ) ) {
  179. $file_data['pgcache.bad_behavior_path'] = '';
  180. } else {
  181. if ( file_exists( WP_PLUGIN_DIR . '/bad-behavior/bad-behavior-generic.php' ) ) {
  182. $bb_file = WP_PLUGIN_DIR . '/bad-behavior/bad-behavior-generic.php';
  183. } elseif ( file_exists( WP_PLUGIN_DIR . '/Bad-Behavior/bad-behavior-generic.php' ) ) {
  184. $bb_file = WP_PLUGIN_DIR . '/Bad-Behavior/bad-behavior-generic.php';
  185. } else {
  186. $bb_file = false;
  187. }
  188. if ( $bb_file ) {
  189. $file_data['pgcache.bad_behavior_path'] = $bb_file;
  190. }
  191. }
  192. //
  193. // changes in 0.13
  194. //
  195. if ( version_compare( $file_data['version'], '0.12.0', '<=' ) ) {
  196. if ( empty( $file_data['lazyload.exclude'] ) ) {
  197. $file_data['lazyload.exclude'] = array();
  198. }
  199. if ( !in_array( 'skip_lazy', $file_data['lazyload.exclude'] ) ) {
  200. $file_data['lazyload.exclude'][] = 'skip_lazy';
  201. }
  202. }
  203. //
  204. // changes in 0.9.7
  205. //
  206. if ( isset( $file_data['cdnfsd.enabled'] ) &&
  207. $file_data['cdnfsd.enabled'] == '1' &&
  208. empty( $file_data['cdnfsd.engine'] ) ) {
  209. $file_data['cdnfsd.enabled'] = '0';
  210. }
  211. //
  212. // changes in 0.9.6
  213. //
  214. if ( !isset( $file_data['cdn.cors_header'] ) ) {
  215. $file_data['cdn.cors_header'] = true;
  216. }
  217. if ( isset( $file_data['cdn.engine'] ) && $file_data['cdn.engine'] == 'netdna' ) {
  218. $file_data['cdn.engine'] = 'maxcdn';
  219. $file_data['cdn.maxcdn.authorization_key'] = $file_data['cdn.netdna.authorization_key'];
  220. $file_data['cdn.maxcdn.domain'] = $file_data['cdn.netdna.domain'];
  221. $file_data['cdn.maxcdn.ssl'] = $file_data['cdn.netdna.ssl'];
  222. $file_data['cdn.maxcdn.zone_id'] = $file_data['cdn.netdna.zone_id'];
  223. }
  224. //
  225. // changes in 0.9.5
  226. //
  227. if ( !isset( $file_data['extensions.active_frontend'] ) ||
  228. !is_array( $file_data['extensions.active_frontend'] ) )
  229. $file_data['extensions.active_frontend'] = array();
  230. if ( version_compare( $file_data['version'], '0.9.5', '<' ) ) {
  231. // dont show minify tips if already enabled
  232. if ( isset( $file_data['minify.enabled'] ) &&
  233. $file_data['minify.enabled'] == 'true' &&
  234. function_exists( 'get_option' ) ) {
  235. $cs = Dispatcher::config_state();
  236. $cs->set( 'minify.hide_minify_help', true );
  237. $cs->save();
  238. }
  239. $file_data['pgcache.mirrors.enabled'] = true;
  240. // map regions in rackspace
  241. if ( isset( $file_data['cdn.rscf.location'] ) ) {
  242. if ( $file_data['cdn.rscf.location'] == 'uk' )
  243. $file_data['cdn.rscf.location'] = 'LON';
  244. if ( $file_data['cdn.rscf.location'] == 'us' )
  245. $file_data['cdn.rscf.location'] = 'ORD';
  246. }
  247. // change filenames
  248. $active = array();
  249. if ( isset( $file_data['extensions.active'] ) &&
  250. is_array( $file_data['extensions.active'] ) ) {
  251. if ( isset( $file_data['extensions.active']['cloudflare'] ) )
  252. $active['cloudflare'] = 'w3-total-cache/Extension_CloudFlare_Plugin.php';
  253. if ( isset( $file_data['extensions.active']['feedburner'] ) )
  254. $active['feedburner'] = 'w3-total-cache/Extension_FeedBurner_Plugin.php';
  255. if ( isset( $file_data['extensions.active']['genesis.theme'] ) )
  256. $active['genesis.theme'] = 'w3-total-cache/Extension_Genesis_Plugin.php';
  257. if ( isset( $file_data['extensions.active']['wordpress-seo'] ) )
  258. $active['wordpress-seo'] = 'w3-total-cache/Extension_WordPressSeo_Plugin.php';
  259. }
  260. $file_data['extensions.active'] = $active;
  261. $active_frontend = array();
  262. foreach ( $active as $key => $value )
  263. $active_frontend[$key] = '*';
  264. $file_data['extensions.active_frontend'] = $active_frontend;
  265. // keep those active by default
  266. $file_data['extensions.active']['newrelic'] =
  267. 'w3-total-cache/Extension_NewRelic_Plugin.php';
  268. $file_data['extensions.active']['fragmentcache'] =
  269. 'w3-total-cache/Extension_FragmentCache_Plugin.php';
  270. }
  271. // newrelic settings - migrate to extension
  272. if ( isset( $file_data['newrelic.enabled'] ) &&
  273. $file_data['newrelic.enabled'] ) {
  274. // make new relic extension enabled
  275. if ( !isset( $file_data['extensions.active_frontend']['newrelic'] ) )
  276. $file_data['extensions.active_frontend']['newrelic'] ='*';
  277. }
  278. if ( !isset( $file_data['newrelic'] ) ||
  279. !is_array( $file_data['newrelic'] ) )
  280. $file_data['newrelic'] = array(
  281. 'monitoring_type' => 'apm'
  282. );
  283. $this->_set_if_exists( $file_data, 'newrelic.api_key',
  284. 'newrelic', 'api_key' );
  285. $this->_set_if_exists( $file_data, 'newrelic.appname',
  286. 'newrelic', 'apm.application_name' );
  287. $this->_set_if_exists( $file_data, 'newrelic.accept.logged_roles',
  288. 'newrelic', 'accept.logged_roles' );
  289. $this->_set_if_exists( $file_data, 'newrelic.accept.roles',
  290. 'newrelic', 'accept.roles' );
  291. $this->_set_if_exists( $file_data, 'newrelic.use_php_function',
  292. 'newrelic', 'use_php_function' );
  293. $this->_set_if_exists( $file_data, 'newrelic.cache_time',
  294. 'newrelic', 'cache_time' );
  295. $this->_set_if_exists( $file_data, 'newrelic.enable_xmit',
  296. 'newrelic', 'enable_xmit' );
  297. $this->_set_if_exists( $file_data, 'newrelic.include_rum',
  298. 'newrelic', 'include_rum' );
  299. // extensions - kept in separate key now
  300. $this->_set_if_exists_extension( $file_data, 'cloudflare' );
  301. $this->_set_if_exists_extension( $file_data, 'genesis.theme' );
  302. $this->_set_if_exists_extension( $file_data, 'feedburner' );
  303. // fragmentcache to extension
  304. if ( isset( $file_data['fragmentcache.enabled'] ) &&
  305. $file_data['fragmentcache.enabled'] ) {
  306. // make new relic extension enabled
  307. if ( !isset( $file_data['extensions.active_frontend']['fragmentcache'] ) )
  308. $file_data['extensions.active_frontend']['fragmentcache'] = '*';
  309. }
  310. $this->_set_if_exists( $file_data, 'fragmentcache.debug',
  311. 'fragmentcache', 'debug' );
  312. $this->_set_if_exists( $file_data, 'fragmentcache.engine',
  313. 'fragmentcache', 'engine' );
  314. $this->_set_if_exists( $file_data, 'fragmentcache.file.gc',
  315. 'fragmentcache', 'file.gc' );
  316. $this->_set_if_exists( $file_data, 'fragmentcache.file.locking',
  317. 'fragmentcache', 'file.locking' );
  318. $this->_set_if_exists( $file_data, 'fragmentcache.memcached.servers',
  319. 'fragmentcache', 'memcached.servers' );
  320. $this->_set_if_exists( $file_data, 'fragmentcache.memcached.persistent',
  321. 'fragmentcache', 'memcached.persistent' );
  322. $this->_set_if_exists( $file_data, 'fragmentcache.memcached.aws_autodiscovery',
  323. 'fragmentcache', 'memcached.aws_autodiscovery' );
  324. $this->_set_if_exists( $file_data, 'fragmentcache.memcached.username',
  325. 'fragmentcache', 'memcached.username' );
  326. $this->_set_if_exists( $file_data, 'fragmentcache.memcached.password',
  327. 'fragmentcache', 'memcached.password' );
  328. $this->_set_if_exists( $file_data, 'fragmentcache.memcached.binary_protocol',
  329. 'fragmentcache', 'memcached.binary_protocol' );
  330. $this->_set_if_exists( $file_data, 'fragmentcache.redis.persistent',
  331. 'fragmentcache', 'redis.persistent' );
  332. $this->_set_if_exists( $file_data, 'fragmentcache.redis.servers',
  333. 'fragmentcache', 'redis.servers' );
  334. $this->_set_if_exists( $file_data, 'fragmentcache.redis.password',
  335. 'fragmentcache', 'redis.password' );
  336. $this->_set_if_exists( $file_data, 'fragmentcache.redis.dbid',
  337. 'fragmentcache', 'redis.dbid' );
  338. $this->_set_if_exists( $file_data, 'fragmentcache.lifetime',
  339. 'fragmentcache', 'lifetime' );
  340. // new options, separated old one. implemented in 0.9.5.3
  341. if ( isset( $file_data['browsercache.cssjs.replace'] ) &&
  342. !isset( $file_data['browsercache.cssjs.querystring'] ) ) {
  343. $file_data['browsercache.cssjs.querystring'] = $file_data['browsercache.cssjs.replace'];
  344. }
  345. if ( isset( $file_data['browsercache.other.replace'] ) &&
  346. !isset( $file_data['browsercache.other.querystring'] ) ) {
  347. $file_data['browsercache.other.querystring'] = $file_data['browsercache.other.replace'];
  348. }
  349. //
  350. // changes in 0.9.5.4
  351. //
  352. if ( isset( $file_data['cdn.engine'] ) ) {
  353. if ( $file_data['cdn.engine'] == 'maxcdn_fsd' ) {
  354. $file_data['cdnfsd.engine'] = 'maxcdn';
  355. $file_data['cdnfsd.enabled'] = $file_data['cdn.enabled'];
  356. if ( isset( $file_data['cdn.maxcdn_fsd.api_key'] ) ) {
  357. $file_data['cdnfsd.maxcdn.api_key'] =
  358. $file_data['cdn.maxcdn_fsd.api_key'];
  359. $file_data['cdnfsd.maxcdn.zone_id'] =
  360. $file_data['cdn.maxcdn_fsd.zone_id'];
  361. $file_data['cdnfsd.maxcdn.zone_domain'] =
  362. $file_data['cdn.maxcdn_fsd.zone_domain'];
  363. }
  364. }
  365. if ( $file_data['cdn.engine'] == 'cloudfront_fsd' ) {
  366. $file_data['cdnfsd.engine'] = 'cloudfront';
  367. $file_data['cdnfsd.enabled'] = $file_data['cdn.enabled'];
  368. if ( isset( $file_data['cdn.cloudfront_fsd.access_key'] ) ) {
  369. $file_data['cdnfsd.cloudfront.access_key'] =
  370. $file_data['cdn.cloudfront_fsd.access_key'];
  371. $file_data['cdnfsd.cloudfront.distribution_domain'] =
  372. $file_data['cdn.cloudfront_fsd.distribution_domain'];
  373. $file_data['cdnfsd.cloudfront.secret_key'] =
  374. $file_data['cdn.cloudfront_fsd.secret_key'];
  375. $file_data['cdnfsd.cloudfront.distribution_id'] =
  376. $file_data['cdn.cloudfront_fsd.distribution_id'];
  377. }
  378. }
  379. }
  380. $file_data['version'] = W3TC_VERSION;
  381. return $file_data;
  382. }
  383. private function _set_if_exists_extension( &$a, $extension ) {
  384. if ( isset( $a['extensions.settings'] ) &&
  385. isset( $a['extensions.settings'][$extension] ) ) {
  386. $a[$extension] = $a['extensions.settings'][$extension];
  387. unset( $a['extensions.settings'][$extension] );
  388. }
  389. }
  390. private function _set_if_exists( &$a, $old_key, $new_key0, $new_key1 ) {
  391. if ( isset( $a[$old_key] ) ) {
  392. $a[$new_key0][$new_key1] = $a[$old_key];
  393. unset( $a[$old_key] );
  394. }
  395. }
  396. }