193 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace Sphere\Debloat;
 | |
| 
 | |
| use Sphere\Debloat\OptimizeCss\Stylesheet;
 | |
| use Sphere\Debloat\OptimizeJs\Script;
 | |
| 
 | |
| /**
 | |
|  * Delay load assets singleton.
 | |
|  * 
 | |
|  * @author  asadkn
 | |
|  * @since   1.0.0
 | |
|  */
 | |
| class DelayLoad
 | |
| {
 | |
| 	public $enabled = true;
 | |
| 	public $use_js = false;
 | |
| 	public $js_type;
 | |
| 
 | |
| 	public $preload = [];
 | |
| 	
 | |
| 	/**
 | |
| 	 * Note: Should be used a singleton.
 | |
| 	 */
 | |
| 	public function __construct()
 | |
| 	{
 | |
| 		$this->register_hooks();
 | |
| 	}
 | |
| 
 | |
| 	public function register_hooks()
 | |
| 	{
 | |
| 		// add_action('wp_enqueue_scripts', [$this, 'register_assets']);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Enable injection of required scripts and preloads, as needed. 
 | |
| 	 *
 | |
| 	 * @param null|true $use_js Whether to inject delay/defer JS. null keeps the current.
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	public function enable($use_js = null)
 | |
| 	{
 | |
| 		$this->enabled = true;
 | |
| 
 | |
|         if ($use_js === true) {
 | |
|             $this->use_js = $use_js;
 | |
|         }
 | |
| 	}
 | |
| 
 | |
| 	public function disable()
 | |
| 	{
 | |
| 		$this->enabled = false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Enqueue a preload.
 | |
| 	 *
 | |
| 	 * @param Stylesheet|Script $asset
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	public function add_preload($asset)
 | |
| 	{
 | |
| 		$this->preload[] = $asset;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add extras to the provided HTML buffer.
 | |
| 	 *
 | |
| 	 * @param string $html
 | |
| 	 * @return string
 | |
| 	 */
 | |
| 	public function render($html)
 | |
| 	{
 | |
| 		if (!$this->enabled) {
 | |
| 			return $html;
 | |
| 		}
 | |
| 
 | |
| 		$js = $this->render_js();
 | |
| 		$preloads = $this->render_preloads();
 | |
| 
 | |
| 		$append = $preloads . $js;
 | |
| 
 | |
| 		// Add to body or at the end.
 | |
| 		// Note: Has to be at the end to ensure all <script> tags with defer has been added.
 | |
| 		if (strpos($html, '</body>') !== false) {
 | |
| 			$html = str_replace('</body>', $append . "\n</body>", $html);
 | |
| 		} else {
 | |
| 			$html .=  $append;
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		return $html;
 | |
| 	}
 | |
| 
 | |
| 	protected function render_preloads()
 | |
| 	{
 | |
| 		$preloads = [];
 | |
| 		foreach ($this->preload as $preload) {
 | |
| 			$media = 'all';
 | |
| 			$type  = ($preload instanceof Stylesheet) ? 'style' : 'script';
 | |
| 
 | |
| 			if ($type === 'style') {
 | |
| 				$media = $preload->media ?: $media;
 | |
| 			}
 | |
| 
 | |
| 			$preloads[] = sprintf(
 | |
| 				'<link rel="prefetch" href="%1$s" as="%2$s" media="%3$s" />',
 | |
| 				esc_url($preload->get_content_url()),
 | |
| 				$type,
 | |
| 				esc_attr($media)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		return implode('', $preloads);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get JS enqueues and inline scripts as needed.
 | |
| 	 *
 | |
| 	 * @return string
 | |
| 	 */
 | |
| 	protected function render_js()
 | |
| 	{
 | |
| 		if (!$this->use_js) {
 | |
| 			return '';
 | |
| 		}
 | |
| 
 | |
| 		$js  = '';
 | |
| 		$min = Plugin::get_instance()->env !== 'dev' ? '.min' : '';
 | |
| 
 | |
| 		// Defer JS is always inline.
 | |
| 		$js .= sprintf(
 | |
| 			'<script data-cfasync="false">%s</script>',
 | |
| 			Plugin::file_system()->get_contents(
 | |
| 				Plugin::get_instance()->dir_path . 'inc/delay-load/js/defer-load'. $min .'.js'
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		// Delay load JS comes after, just in case, to not mess up readyState.
 | |
| 		if ($this->js_type === 'inline') {
 | |
| 			$js .= sprintf(
 | |
| 				'<script data-cfasync="false">%s</script>',
 | |
| 				Plugin::file_system()->get_contents(
 | |
| 					Plugin::get_instance()->dir_path . 'inc/delay-load/js/delay-load'. $min .'.js'
 | |
| 				)
 | |
| 			);
 | |
| 
 | |
| 		} else {
 | |
| 
 | |
| 			$js .= sprintf(
 | |
| 				'<script type="text/javascript" src="%s" data-cfasync="false"></script>',
 | |
| 				esc_url(Plugin::get_instance()->dir_url . 'inc/delay-load/js/delay-load'. $min .'.js?ver=' . Plugin::VERSION)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		if (!$js) {
 | |
| 			return '';
 | |
| 		}
 | |
| 
 | |
| 		/**
 | |
| 		 * Add configs.
 | |
| 		 */
 | |
| 		$configs = [
 | |
| 			'cssDelayType' => Plugin::options()->delay_css_type,
 | |
| 			'jsDelayType'  => Plugin::options()->delay_js_type,
 | |
| 			'jsDelayMax'   => Plugin::options()->delay_js_max
 | |
| 		];
 | |
| 
 | |
| 		$js = sprintf(
 | |
| 			'<script>var debloatConfig = %1$s;</script>%2$s',
 | |
| 			json_encode($configs),
 | |
| 			$js
 | |
| 		);
 | |
| 
 | |
| 		return $js;
 | |
| 	}
 | |
| 	
 | |
| 	/**
 | |
| 	 * Check for conditionals for delay load.
 | |
| 	 *
 | |
| 	 * @return boolean
 | |
| 	 */
 | |
| 	public function should_delay_css()
 | |
| 	{
 | |
| 		if (!Plugin::options()->delay_css_load) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$valid = Plugin::process()->check_enabled(Plugin::options()->delay_css_on);
 | |
| 
 | |
| 		return apply_filters('debloat/should_delay_css', $valid);
 | |
| 	}
 | |
| } |