Created
August 27, 2011 19:58
-
-
Save junaidpv/1175799 to your computer and use it in GitHub Desktop.
Class that helps to load resources with dependencies easily, such as JavaScripts, CSSs
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 | |
/** | |
* @author Junaid P V (http://junaidpv.in) | |
* @license GPLv3 | |
*/ | |
/** | |
* Class that helps to load resource easily, such as JavaScripts, CSSs | |
* | |
* @version 1.0 | |
*/ | |
class Resource_loader { | |
private $libraryResources = array(); | |
private $resources = array(); | |
/** | |
* Add resources that reside on disk. | |
* | |
* @param array $resources | |
*/ | |
public function add($resources) { | |
foreach ($resources as $name => $resource) { | |
// It is always resource links added with this method | |
$tmpArray = array('type' => 'link'); | |
// Add scripts if given | |
if (isset($resource['scripts'])) { | |
$tmpArray['scripts'] = $this->alwaysArray($resource['scripts']); | |
} | |
// Add styles if given | |
if (isset($resource['styles'])) { | |
$tmpArray['styles'] = $this->alwaysArray($resource['styles']); | |
} | |
if (isset($resource['dependencies'])) { | |
$tmpArray['dependencies'] = $this->alwaysArray( | |
$resource['dependencies'] | |
); | |
} | |
$this->resources[$name] = $tmpArray; | |
} | |
} | |
/** | |
* Add library resources. | |
* Resource added by this method will be loaded | |
* when there is at leat one dependance for it | |
* | |
* @param array $resources | |
*/ | |
public function addLibrary($resources) { | |
foreach ($resources as $name => $resource) { | |
// It is always resource links added with this method | |
$tmpArray = array('type' => 'link'); | |
// Add scripts if given | |
if (isset($resource['scripts'])) { | |
$tmpArray['scripts'] = $this->alwaysArray($resource['scripts']); | |
} | |
// Add styles if given | |
if (isset($resource['styles'])) { | |
$tmpArray['styles'] = $this->alwaysArray($resource['styles']); | |
} | |
if (isset($resource['dependencies'])) { | |
$tmpArray['dependencies'] = $this->alwaysArray( | |
$resource['dependencies'] | |
); | |
} | |
$this->libraryResources[$name] = $tmpArray; | |
} | |
} | |
/** | |
* Add resouces (JS and CSS) as raw string. | |
* | |
* @param array $resources | |
*/ | |
public function addRaw($resources) { | |
foreach ($resources as $name => $resource) { | |
// It is always raw resources added by this method | |
$tmpArray = array('type' => 'raw'); | |
if (isset($resource['scripts'])) { | |
$tmpArray['scripts'] = $this->alwaysArray($resource['scripts']); | |
} | |
if (isset($resource['styles'])) { | |
$tmpArray['styles'] = $this->alwaysArray($resource['styles']); | |
} | |
if (isset($resource['dependencies'])) { | |
$tmpArray['dependencies'] = $this->alwaysArray( | |
$resource['dependencies'] | |
); | |
} | |
$this->resources[$name] = $tmpArray; | |
} | |
} | |
/** | |
* Add raw library resources. | |
* Resource added by this method will be loaded | |
* when there is at leat one dependance for it | |
* | |
* @param array $resources | |
*/ | |
public function addRawLibrary($resources) { | |
foreach ($resources as $name => $resource) { | |
// It is always raw resources added by this method | |
$tmpArray = array('type' => 'raw'); | |
if (isset($resource['scripts'])) { | |
$tmpArray['scripts'] = $this->alwaysArray($resource['scripts']); | |
} | |
if (isset($resource['styles'])) { | |
$tmpArray['styles'] = $this->alwaysArray($resource['styles']); | |
} | |
if (isset($resource['dependencies'])) { | |
$tmpArray['dependencies'] = | |
$this->alwaysArray($resource['dependencies']); | |
} | |
$this->libraryResources[$name] = $tmpArray; | |
} | |
} | |
/** | |
* Returns HTML snippet that can be inserted on web pages | |
* to be send to client. | |
* Caution: This funtion must not be called more than once. | |
* | |
* @return string | |
*/ | |
public function render() { | |
// Get all resources in correct order. | |
$ordered = $this->getOrdered(); | |
// Start with a blank html snippet. | |
$html = ''; | |
foreach ($ordered as $res) { | |
if ($res['type'] == 'raw') { | |
// It is a raw resouce, we need to add the source code. | |
if (isset($res['scripts'])) { | |
$html .= "\n".'<script type="text/javascript">'; | |
foreach ($res['scripts'] as $script) { | |
$html .= "\n" . $script; | |
} | |
$html .= '</script>'; | |
} | |
if (isset($res['styles'])) { | |
$html .= "\n".'<style type="text/css">'; | |
foreach ($res['styles'] as $style) { | |
$html .= "\n" . $style; | |
} | |
$html .= '</style>'; | |
} | |
} elseif ($res['type'] == 'link') { | |
if (isset($res['scripts'])) { | |
foreach ($res['scripts'] as $script) { | |
$html .= "\n" . '<script type="text/javascript" src="' | |
. $script . '"></script>'; | |
} | |
} | |
if (isset($res['styles'])) { | |
foreach ($res['styles'] as $style) { | |
$html .= "\n" | |
. '<link rel="stylesheet" type="text/css" href="' | |
. $style . '" />'; | |
} | |
} | |
} | |
} | |
return $html; | |
} | |
/** | |
* Get resource array having all resources in correct order. | |
*/ | |
private function getOrdered() { | |
// Get the unordered resource array. | |
$source = $this->resources; | |
// Create a blank ordered array to start with. | |
$ordered = array(); | |
// Itereate over all items in unordered resource array to put every | |
// item in correct order. | |
while (true) { | |
if (count($source) == 0) { | |
// No more item in $source, let's stop it | |
break; | |
} | |
// Get frist item in $source | |
$pair = $this->array_kshift($source); | |
// and put that item in correct order at $ordered. | |
// putItemAtCorrectPosition will manage dependent items. | |
$this->putItemAtCorrectPosition($pair[0], $pair[1], $ordered); | |
} | |
return $ordered; | |
} | |
/** | |
* Put the specified item at correct position in $ordered. | |
* If depended item(s) are in $source they will be put before the item. | |
* | |
* @param array $item | |
* @param array $ordered | |
* @param array $source | |
*/ | |
private function putItemAtCorrectPosition($resourceName, $resource, &$ordered) { | |
// Let's check about dependecies before putting item in $ordered. | |
if (isset($resource['dependencies'])) { | |
// Check whether any depended resource in $source | |
// since all depended items should be in $ordered before | |
// the current item put in. | |
foreach ($resource['dependencies'] as $subject) { | |
if (array_key_exists($subject, $ordered)) { | |
// Depended is already included | |
continue; | |
} | |
else { | |
$source = null; | |
if (array_key_exists($subject, $this->libraryResources)) { | |
// Dependency is on library | |
$source = $this->libraryResources; | |
} | |
elseif (array_key_exists($subject, $this->resources)) { | |
// Dependency is on normal resource | |
$source = $this->resources; | |
} | |
else { | |
// Depended resource is not available at all. | |
// It is mistake and let us throw and | |
// exception informing about it. | |
throw new Exception( | |
"Depended item '$subject' could not be found" | |
); | |
} | |
// Take a copy of it from source | |
$depended = $source[$subject]; | |
// Remove it from source | |
unset($source[$subject]); | |
// And put the depended item in $ordered | |
// at correct position | |
$this->putItemAtCorrectPosition( | |
$subject, | |
$depended, | |
$ordered | |
); | |
} | |
} | |
} | |
// We have already put every depended items in correct position, | |
// so put current item at the end of $ordered. | |
$ordered[$resourceName] = $resource; | |
} | |
private function alwaysArray($value) { | |
return (is_array($value) ? $value : array($value)); | |
} | |
/** | |
* Array shift with key | |
* | |
* @param array $arr | |
* @return array | |
*/ | |
private function array_kshift(&$arr) { | |
list($k) = array_keys($arr); | |
$r = array($k, $arr[$k]); | |
unset($arr[$k]); | |
return $r; | |
} | |
/** | |
* Sometimes some libraries needs to be loaded even some other script has | |
* no dependency on them, like posabsolute jquery validation. | |
* | |
* @param string $name | |
*/ | |
public function alwaysLoadLibrary($name) { | |
if (!array_key_exists($name, $this->resources)) { | |
// No need to add if the library is already as normal resource | |
if(array_key_exists($name, $this->libraryResources)) { | |
// Move resource from library to normal | |
// so it will be loaded always | |
$this->resources[$name] = $this->libraryResources[$name]; | |
// then remove from library | |
unset ($this->libraryResources[$name]); | |
} | |
else { | |
// Resource is not on both library and normal resources | |
throw new Exception( | |
"Library '$name' not yet added!" | |
); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment