mirror of
https://github.com/there4/markdown-resume.git
synced 2024-12-03 08:59:35 -05:00
This includes several vendor libraries: Assetic, LessPHP, Mustache, SmartyPants, Markdown
387 lines
11 KiB
PHP
Executable File
387 lines
11 KiB
PHP
Executable File
<?php
|
|
|
|
/*
|
|
* This file is part of the Assetic package, an OpenSky project.
|
|
*
|
|
* (c) 2010-2011 OpenSky Project Inc
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Assetic\Factory;
|
|
|
|
use Assetic\Asset\AssetCollection;
|
|
use Assetic\Asset\AssetCollectionInterface;
|
|
use Assetic\Asset\AssetInterface;
|
|
use Assetic\Asset\AssetReference;
|
|
use Assetic\Asset\FileAsset;
|
|
use Assetic\Asset\GlobAsset;
|
|
use Assetic\Asset\HttpAsset;
|
|
use Assetic\AssetManager;
|
|
use Assetic\Factory\Worker\WorkerInterface;
|
|
use Assetic\FilterManager;
|
|
|
|
/**
|
|
* The asset factory creates asset objects.
|
|
*
|
|
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
|
*/
|
|
class AssetFactory
|
|
{
|
|
private $root;
|
|
private $debug;
|
|
private $output;
|
|
private $workers;
|
|
private $am;
|
|
private $fm;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param string $root The default root directory
|
|
* @param string $output The default output string
|
|
* @param Boolean $debug Filters prefixed with a "?" will be omitted in debug mode
|
|
*/
|
|
public function __construct($root, $debug = false)
|
|
{
|
|
$this->root = rtrim($root, '/');
|
|
$this->debug = $debug;
|
|
$this->output = 'assetic/*';
|
|
$this->workers = array();
|
|
}
|
|
|
|
/**
|
|
* Sets debug mode for the current factory.
|
|
*
|
|
* @param Boolean $debug Debug mode
|
|
*/
|
|
public function setDebug($debug)
|
|
{
|
|
$this->debug = $debug;
|
|
}
|
|
|
|
/**
|
|
* Checks if the factory is in debug mode.
|
|
*
|
|
* @return Boolean Debug mode
|
|
*/
|
|
public function isDebug()
|
|
{
|
|
return $this->debug;
|
|
}
|
|
|
|
/**
|
|
* Sets the default output string.
|
|
*
|
|
* @param string $output The default output string
|
|
*/
|
|
public function setDefaultOutput($output)
|
|
{
|
|
$this->output = $output;
|
|
}
|
|
|
|
/**
|
|
* Adds a factory worker.
|
|
*
|
|
* @param WorkerInterface $worker A worker
|
|
*/
|
|
public function addWorker(WorkerInterface $worker)
|
|
{
|
|
$this->workers[] = $worker;
|
|
}
|
|
|
|
/**
|
|
* Returns the current asset manager.
|
|
*
|
|
* @return AssetManager|null The asset manager
|
|
*/
|
|
public function getAssetManager()
|
|
{
|
|
return $this->am;
|
|
}
|
|
|
|
/**
|
|
* Sets the asset manager to use when creating asset references.
|
|
*
|
|
* @param AssetManager $am The asset manager
|
|
*/
|
|
public function setAssetManager(AssetManager $am)
|
|
{
|
|
$this->am = $am;
|
|
}
|
|
|
|
/**
|
|
* Returns the current filter manager.
|
|
*
|
|
* @return FilterManager|null The filter manager
|
|
*/
|
|
public function getFilterManager()
|
|
{
|
|
return $this->fm;
|
|
}
|
|
|
|
/**
|
|
* Sets the filter manager to use when adding filters.
|
|
*
|
|
* @param FilterManager $fm The filter manager
|
|
*/
|
|
public function setFilterManager(FilterManager $fm)
|
|
{
|
|
$this->fm = $fm;
|
|
}
|
|
|
|
/**
|
|
* Creates a new asset.
|
|
*
|
|
* Prefixing a filter name with a question mark will cause it to be
|
|
* omitted when the factory is in debug mode.
|
|
*
|
|
* Available options:
|
|
*
|
|
* * output: An output string
|
|
* * name: An asset name for interpolation in output patterns
|
|
* * debug: Forces debug mode on or off for this asset
|
|
* * root: An array or string of more root directories
|
|
*
|
|
* @param array|string $inputs An array of input strings
|
|
* @param array|string $filters An array of filter names
|
|
* @param array $options An array of options
|
|
*
|
|
* @return AssetCollection An asset collection
|
|
*/
|
|
public function createAsset($inputs = array(), $filters = array(), array $options = array())
|
|
{
|
|
if (!is_array($inputs)) {
|
|
$inputs = array($inputs);
|
|
}
|
|
|
|
if (!is_array($filters)) {
|
|
$filters = array($filters);
|
|
}
|
|
|
|
if (!isset($options['output'])) {
|
|
$options['output'] = $this->output;
|
|
}
|
|
|
|
if (!isset($options['vars'])) {
|
|
$options['vars'] = array();
|
|
}
|
|
|
|
if (!isset($options['debug'])) {
|
|
$options['debug'] = $this->debug;
|
|
}
|
|
|
|
if (!isset($options['root'])) {
|
|
$options['root'] = array($this->root);
|
|
} else {
|
|
if (!is_array($options['root'])) {
|
|
$options['root'] = array($options['root']);
|
|
}
|
|
|
|
$options['root'][] = $this->root;
|
|
}
|
|
|
|
if (!isset($options['name'])) {
|
|
$options['name'] = $this->generateAssetName($inputs, $filters, $options);
|
|
}
|
|
|
|
$asset = $this->createAssetCollection(array(), $options);
|
|
$extensions = array();
|
|
|
|
// inner assets
|
|
foreach ($inputs as $input) {
|
|
if (is_array($input)) {
|
|
// nested formula
|
|
$asset->add(call_user_func_array(array($this, 'createAsset'), $input));
|
|
} else {
|
|
$asset->add($this->parseInput($input, $options));
|
|
$extensions[pathinfo($input, PATHINFO_EXTENSION)] = true;
|
|
}
|
|
}
|
|
|
|
// filters
|
|
foreach ($filters as $filter) {
|
|
if ('?' != $filter[0]) {
|
|
$asset->ensureFilter($this->getFilter($filter));
|
|
} elseif (!$options['debug']) {
|
|
$asset->ensureFilter($this->getFilter(substr($filter, 1)));
|
|
}
|
|
}
|
|
|
|
// append variables
|
|
if (!empty($options['vars'])) {
|
|
$toAdd = array();
|
|
foreach ($options['vars'] as $var) {
|
|
if (false !== strpos($options['output'], '{'.$var.'}')) {
|
|
continue;
|
|
}
|
|
|
|
$toAdd[] = '{'.$var.'}';
|
|
}
|
|
|
|
if ($toAdd) {
|
|
$options['output'] = str_replace('*', '*.'.implode('.', $toAdd), $options['output']);
|
|
}
|
|
}
|
|
|
|
// append consensus extension if missing
|
|
if (1 == count($extensions) && !pathinfo($options['output'], PATHINFO_EXTENSION) && $extension = key($extensions)) {
|
|
$options['output'] .= '.'.$extension;
|
|
}
|
|
|
|
// output --> target url
|
|
$asset->setTargetPath(str_replace('*', $options['name'], $options['output']));
|
|
|
|
// apply workers and return
|
|
return $this->applyWorkers($asset);
|
|
}
|
|
|
|
public function generateAssetName($inputs, $filters, $options = array())
|
|
{
|
|
foreach (array_diff(array_keys($options), array('output', 'debug', 'root')) as $key) {
|
|
unset($options[$key]);
|
|
}
|
|
|
|
ksort($options);
|
|
|
|
return substr(sha1(serialize($inputs).serialize($filters).serialize($options)), 0, 7);
|
|
}
|
|
|
|
/**
|
|
* Parses an input string string into an asset.
|
|
*
|
|
* The input string can be one of the following:
|
|
*
|
|
* * A reference: If the string starts with an "at" sign it will be interpreted as a reference to an asset in the asset manager
|
|
* * An absolute URL: If the string contains "://" or starts with "//" it will be interpreted as an HTTP asset
|
|
* * A glob: If the string contains a "*" it will be interpreted as a glob
|
|
* * A path: Otherwise the string is interpreted as a filesystem path
|
|
*
|
|
* Both globs and paths will be absolutized using the current root directory.
|
|
*
|
|
* @param string $input An input string
|
|
* @param array $options An array of options
|
|
*
|
|
* @return AssetInterface An asset
|
|
*/
|
|
protected function parseInput($input, array $options = array())
|
|
{
|
|
if ('@' == $input[0]) {
|
|
return $this->createAssetReference(substr($input, 1));
|
|
}
|
|
|
|
if (false !== strpos($input, '://') || 0 === strpos($input, '//')) {
|
|
return $this->createHttpAsset($input, $options['vars']);
|
|
}
|
|
|
|
if (self::isAbsolutePath($input)) {
|
|
if ($root = self::findRootDir($input, $options['root'])) {
|
|
$path = ltrim(substr($input, strlen($root)), '/');
|
|
} else {
|
|
$path = null;
|
|
}
|
|
} else {
|
|
$root = $this->root;
|
|
$path = $input;
|
|
$input = $this->root.'/'.$path;
|
|
}
|
|
if (false !== strpos($input, '*')) {
|
|
return $this->createGlobAsset($input, $root, $options['vars']);
|
|
} else {
|
|
return $this->createFileAsset($input, $root, $path, $options['vars']);
|
|
}
|
|
}
|
|
|
|
protected function createAssetCollection(array $assets = array(), array $options = array())
|
|
{
|
|
return new AssetCollection($assets, array(), null, isset($options['vars']) ? $options['vars'] : array());
|
|
}
|
|
|
|
protected function createAssetReference($name)
|
|
{
|
|
if (!$this->am) {
|
|
throw new \LogicException('There is no asset manager.');
|
|
}
|
|
|
|
return new AssetReference($this->am, $name);
|
|
}
|
|
|
|
protected function createHttpAsset($sourceUrl, $vars)
|
|
{
|
|
return new HttpAsset($sourceUrl, array(), false, $vars);
|
|
}
|
|
|
|
protected function createGlobAsset($glob, $root = null, $vars)
|
|
{
|
|
return new GlobAsset($glob, array(), $root, $vars);
|
|
}
|
|
|
|
protected function createFileAsset($source, $root = null, $path = null, $vars)
|
|
{
|
|
return new FileAsset($source, array(), $root, $path, $vars);
|
|
}
|
|
|
|
protected function getFilter($name)
|
|
{
|
|
if (!$this->fm) {
|
|
throw new \LogicException('There is no filter manager.');
|
|
}
|
|
|
|
return $this->fm->get($name);
|
|
}
|
|
|
|
/**
|
|
* Filters an asset collection through the factory workers.
|
|
*
|
|
* Each leaf asset will be processed first, followed by the asset
|
|
* collection itself.
|
|
*
|
|
* @param AssetCollectionInterface $asset An asset collection
|
|
*/
|
|
private function applyWorkers(AssetCollectionInterface $asset)
|
|
{
|
|
foreach ($asset as $leaf) {
|
|
foreach ($this->workers as $worker) {
|
|
$retval = $worker->process($leaf);
|
|
|
|
if ($retval instanceof AssetInterface && $leaf !== $retval) {
|
|
$asset->replaceLeaf($leaf, $retval);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($this->workers as $worker) {
|
|
$retval = $worker->process($asset);
|
|
|
|
if ($retval instanceof AssetInterface) {
|
|
$asset = $retval;
|
|
}
|
|
}
|
|
|
|
return $asset instanceof AssetCollectionInterface ? $asset : $this->createAssetCollection(array($asset));
|
|
}
|
|
|
|
static private function isAbsolutePath($path)
|
|
{
|
|
return '/' == $path[0] || '\\' == $path[0] || (3 < strlen($path) && ctype_alpha($path[0]) && $path[1] == ':' && ('\\' == $path[2] || '/' == $path[2]));
|
|
}
|
|
|
|
/**
|
|
* Loops through the root directories and returns the first match.
|
|
*
|
|
* @param string $path An absolute path
|
|
* @param array $roots An array of root directories
|
|
*
|
|
* @return string|null The matching root directory, if found
|
|
*/
|
|
static private function findRootDir($path, array $roots)
|
|
{
|
|
foreach ($roots as $root) {
|
|
if (0 === strpos($path, $root)) {
|
|
return $root;
|
|
}
|
|
}
|
|
}
|
|
}
|