Created
February 25, 2015 10:19
-
-
Save tridungpham/fcf70a091bad4d14d49e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Asset dependencies manager | |
* @author: dphamtri | |
* @date 20140124 | |
*/ | |
class AssetManager | |
{ | |
static $instance = null; | |
public $_resources = array( | |
'js' => array(), | |
'css' => array() | |
); | |
public $_output = array( | |
'js' => array( | |
'optimized' => false, | |
'items' => array(), | |
'items_footer' => array(), | |
'pool' => array(), | |
'echoed' => false | |
), | |
'css' => array( | |
'optimized' => false, | |
'items' => array(), | |
'pool' => array(), | |
'echoed' => false | |
) | |
); | |
/** | |
* Return AssetManager instance | |
* @return AssetManager | |
*/ | |
public static function getInstance() | |
{ | |
if (is_null(self::$instance)) { | |
self::$instance = new self; | |
} | |
return self::$instance; | |
} | |
/** | |
* Add a javascript files to AM | |
* @param string $id | |
* @param string $src | |
* @param array $dep | |
* @param boolean $footer | |
* @return $this | |
*/ | |
public function addJs($id, $src = '', $dep = array(), $footer = false) | |
{ | |
$this->add('js', $id, $src, $dep, $footer); | |
return $this; | |
} | |
/** | |
* Add a stylesheet file to AM | |
* @param string $id | |
* @param string $src | |
* @param array $dep | |
* @param boolean $footer | |
* @return $this | |
*/ | |
public function addCss($id, $src = '', $dep = array(), $footer = false) | |
{ | |
$this->add('css', $id, $src, $dep, $footer); | |
return $this; | |
} | |
public function add($type, $id, $src, $dep = array(), $footer = false) | |
{ | |
if ( $this->_output[$type]['echoed'] ) { | |
$footer = true; | |
} | |
$this->_resources[$type][$id] = array( | |
'id' => $id, | |
'src' => $src, | |
'dependencies' => $dep, | |
'footer' => $footer | |
); | |
$this->setOutputOption($type, 'optimized', false); | |
return $this; | |
} | |
public function setOutputOption($type, $key, $value = null) | |
{ | |
$this->_output[$type][$key] = $value; | |
} | |
public function alterDependencies($type, $key, $value, $append = true) | |
{ | |
$itemToAlter = null; | |
if ( isset($this->_resources[$type][$key])) { | |
$itemToAlter =& $this->_resources[$type][$key]; | |
} | |
if ( ! $itemToAlter ) { | |
return false; | |
} | |
if ($append) { | |
$itemToAlter['dependencies'][] = $value; | |
} else { | |
$itemToAlter['dependencies'] = (array) $value; | |
} | |
if(isset($this->_output[$type]['pool'][$key])) { | |
unset($this->_output[$type]['pool'][$key]); | |
} | |
return true; | |
} | |
public function output($type, $footer = false) | |
{ | |
if (!$this->_output[$type]['optimized']) { | |
$this->optimize($type); | |
} | |
$output = null; | |
if ($footer) { | |
$output = implode("\n", $this->_output[$type]['items_footer']); | |
$this->__remove_outputed_resources($type, array_keys($this->_output[$type]['items_footer'])); | |
} else { | |
$output = implode("\n", $this->_output[$type]['items']); | |
$this->__remove_outputed_resources($type, array_keys($this->_output[$type]['items'])); | |
} | |
$this->_output[$type]['echoed'] = true; | |
return $output; | |
} | |
/** | |
* Optimize assets for outputing | |
* @param string $type Type of asset to optimize | |
* @return void | |
*/ | |
private function optimize($type) | |
{ | |
$resources =& $this->_resources[$type]; | |
$output =& $this->_output[$type]; | |
$output['items'] = array(); | |
$output['items_footer'] = array(); | |
do { | |
$loop = false; | |
$result = array_filter($resources, array($this, "__filter_{$type}_and_return_matches")); | |
if ($result) { | |
// new resource added to pool, continue to run check | |
$loop = true; | |
$this->__merge_output_resources($type, $result); | |
} | |
} while ($loop); | |
$this->_output[$type]['optimized'] = true; | |
} | |
private function __merge_output_resources($type, $items = array()) | |
{ | |
$output =& $this->_output[$type]; | |
$template = $type === 'js' ? "<script type='text/javascript' id='%s' src='%s'></script>" : "<link rel='stylesheet' id='%s' href='%s' />"; | |
foreach ($items as $item) { | |
if ($item['footer'] || $this->__filter_dependecies_in_footer($type, $item['dependencies'])) { | |
$output['items_footer'][$item['id']] = sprintf($template, $item['id'], $item['src']); | |
$output['pool'][$item['id']] = 1; | |
} else { | |
$output['items'][] = sprintf($template, $item['id'], $item['src']); | |
$output['pool'][$item['id']] = 0; | |
} | |
} | |
} | |
private function __remove_outputed_resources($type, $ids) | |
{ | |
$that =& $this; | |
array_walk( | |
$this->_resources[$type], | |
function ($value, $key) use ($ids, $type, $that) { | |
if (in_array($key, $ids)) { | |
unset($that->_resources[$type][$key]); | |
} | |
} | |
); | |
} | |
private function __filter_dependecies_in_footer($type, $dep) | |
{ | |
$pool =& $this->_output[$type]['pool']; | |
foreach ($dep as $d) { | |
if ($pool[$d]) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Filter that return TRUE if all item's dependencies are matched | |
* @param [type] $item [description] | |
* @return bool [type] [description] | |
*/ | |
private function __filter_js_and_return_matches($item) | |
{ | |
if (in_array($item['id'], array_keys($this->_output['js']['pool'])) | |
|| ($item['dependencies'] != array_intersect( | |
$item['dependencies'], | |
array_keys($this->_output['js']['pool']) | |
// $this->_output['js']['pool'] | |
)) | |
) { | |
return false; | |
} | |
return true; | |
} | |
private function __filter_css_and_return_matches($item) | |
{ | |
if (in_array($item['id'], array_keys($this->_output['css']['pool'])) | |
|| ($item['dependencies'] != array_intersect( | |
$item['dependencies'], | |
array_keys($this->_output['css']['pool']) | |
// $this->_output['js']['pool'] | |
)) | |
) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* @param $type | |
* @param array $items | |
* @return $this | |
*/ | |
public function setPool($type, $items = array()) | |
{ | |
if (!in_array($type, array('js', 'css'))) { | |
$type = 'js'; | |
} | |
$pools =& $this->_output[$type]['pool']; | |
foreach ($items as $key => $value) { | |
$pools[$key] = $value; | |
} | |
return $this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment