/** * {@inheritDoc} */ public function parse(\Twig_Token $token) { $inputs = $this->assets; $filters = []; $attributes = ['output' => $this->output, 'var_name' => 'asset_url', 'vars' => []]; $stream = $this->parser->getStream(); while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { if ($stream->test(\Twig_Token::NAME_TYPE, 'filter')) { $filters = array_merge($filters, array_filter(array_map('trim', explode(',', $this->parseValue($stream, false))))); } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'output')) { $attributes['output'] = $this->parseValue($stream, false); } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'debug')) { $attributes['debug'] = $this->parseValue($stream); } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'combine')) { $attributes['combine'] = $this->parseValue($stream); } else { $token = $stream->getCurrent(); throw new \Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', \Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine()); } } $stream->expect(\Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse([$this, 'testEndTag'], true); $stream->expect(\Twig_Token::BLOCK_END_TYPE); $nameUnCompress = $this->factory->generateAssetName($inputs['compress'][0], $filters, $attributes); $nameCompress = substr(sha1(serialize($inputs['uncompress'][0]) . 'oro_assets'), 0, 7); return new OroAsseticNode(['compress' => $this->factory->createAsset($inputs['compress'][0], $filters, $attributes + ['name' => $nameCompress, 'debug' => false]), 'un_compress' => $this->factory->createAsset($inputs['uncompress'][0], [], $attributes + ['name' => $nameUnCompress, 'debug' => true])], ['un_compress' => $nameUnCompress, 'compress' => $nameCompress], $filters, $inputs, $body, $attributes, $token->getLine(), $this->getTag()); }
/** * @param \Twig_NodeInterface $body * @param array $filters * @param array $attributes * @param int $lineno * @return AsseticNode */ protected function createDebugAsseticNode(\Twig_NodeInterface $body, array $filters, array $attributes, $lineno) { $inputs = $this->assetsConfiguration->getCssFiles(true); $name = $this->assetFactory->generateAssetName($inputs, $filters, $attributes); $asset = $this->assetFactory->createAsset($inputs, $filters, $attributes + array('name' => $name)); return new DebugAsseticNode($asset, $body, $inputs, $filters, $name, $attributes, $lineno, $this->getTag()); }
/** * {@inheritDoc} */ public function load(ResourceInterface $resource) { $formulae = array(); $filenames = preg_split("/\n+/", $resource->getContent()); foreach ($filenames as $filename) { if (is_file($filename)) { $name = $this->factory->generateAssetName($filename, array()); $output = $this->mapping->getModulePath($filename); if ($output) { // @see \Assetic\Factory\AssetFactory::createAsset() $formulae[$name] = array($filename, array(), array('output' => $output)); } } } return $formulae; }
/** * {@inheritDoc} */ public function generateAssetName($inputs, $filters, $options = array()) { // Fixes a problem with bad roots if (is_array($options) && isset($options['root'])) { if (!is_array($options['root'])) { $options['root'] = array($options['root']); } // remove empty elements $options['root'] = array_filter($options['root']); // remove duplicate roots $options['root'] = array_unique($options['root']); } return parent::generateAssetName($inputs, $filters, $options); }
/** * Generate the asset name as a hash of the input file modified times. * * @param array $inputs * @param array $filters * @param array $options * @return string */ public function generateAssetName($inputs, $filters, $options = array()) { $name = parent::generateAssetName($inputs, $filters, $options); if ($this->_cacheBustingEnabled) { $hash = hash_init('sha1'); hash_update($hash, $name); $paths = $this->_getFullPaths($inputs); foreach ($paths as $path) { hash_update($hash, file_get_contents($path)); } // Return the final hash $name = hash_final($hash); } return $name; }
public function filterDump(AssetInterface $asset) { $sourceBase = $asset->getSourceRoot(); $sourcePath = $asset->getSourcePath(); $targetPath = $asset->getTargetPath(); $sourceDir = $asset->getSourceDirectory(); if (null === $sourcePath || null === $targetPath || $sourcePath == $targetPath) { return; } // learn how to get from the target back to the source if (false !== strpos($sourceBase, '://')) { list($scheme, $url) = explode('://', $sourceBase . '/' . $sourcePath, 2); list($host, $path) = explode('/', $url, 2); $host = $scheme . '://' . $host . '/'; $path = false === strpos($path, '/') ? '' : dirname($path); $path .= '/'; } else { // assume source and target are on the same host $host = ''; // pop entries off the target until it fits in the source if ('.' == dirname($sourcePath)) { $path = str_repeat('../', substr_count($targetPath, '/')); } elseif ('.' == ($targetDir = dirname($targetPath))) { $path = dirname($sourcePath) . '/'; } else { $path = ''; while (0 !== strpos($sourcePath, $targetDir)) { if (false !== ($pos = strrpos($targetDir, '/'))) { $targetDir = substr($targetDir, 0, $pos); $path .= '../'; } else { $targetDir = ''; $path .= '../'; break; } } $path .= ltrim(substr(dirname($sourcePath) . '/', strlen($targetDir)), '/'); } } $content = $this->filterReferences($asset->getContent(), function ($matches) use($sourceDir, $host) { $path = $sourceDir; if (false !== strpos($matches['url'], '://') || 0 === strpos($matches['url'], '//') || 0 === strpos($matches['url'], 'data:')) { // absolute or protocol-relative or data uri return $matches[0]; } if (isset($matches['url'][0]) && '/' == $matches['url'][0]) { // root relative return str_replace($matches['url'], $host . $matches['url'], $matches[0]); } // document relative $url = $matches['url']; while (0 === strpos($url, '../') && 2 <= substr_count($path, '/')) { $path = substr($path, 0, strrpos(rtrim($path, '/'), '/') + 1); $url = substr($url, 3); } $originalAsset = $path . $url; $originalAsset = reset(preg_split("/[#?]/", $originalAsset)); $rootDir = $this->kernel->getRootDir(); $rootDir = substr($rootDir, 0, -3); $relativeAsset = substr($originalAsset, strlen($rootDir)); $assetName = $this->assetFactory->generateAssetName($relativeAsset); $targetAssetPath = $rootDir . 'web/' . $url; $targetParts = explode('/', $targetAssetPath); $fileName = $assetName . '_' . array_pop($targetParts); array_push($targetParts, $fileName); $targetAssetPath = implode('/', $targetParts); $targetAssetPath = reset(preg_split("/[#?]/", $targetAssetPath)); $urlParts = explode('/', $matches['url']); array_pop($urlParts); array_push($urlParts, $fileName); $urlNew = implode('/', $urlParts); if (!is_dir($dir = dirname($targetAssetPath))) { if (false === @mkdir($dir, 0777, true)) { throw new \RuntimeException('Unable to create directory ' . $dir); } } $asset = new FileAsset($originalAsset); try { $contents = $asset->dump(); } catch (\Exception $e) { echo 'WARNING: ' . $e->getMessage(); } if (false === @file_put_contents($targetAssetPath, $contents)) { throw new \RuntimeException('Unable to write file ' . $targetAssetPath); } $result = str_replace($matches['url'], $urlNew, $matches[0]); return $result; }); $asset->setContent($content); }
/** * Generates an asset name for a list of inputs relative to a given Puli * directory. * * @param string|null $currentDir The Puli directory of the currently loaded * Twig template. This is `null` if the * template was not loaded through Puli. * @param string[] $inputs An array of input strings. * @param string[] $filters An array of filter names. * @param array $options An array of options. * * @return string The asset name. * * @see generateAssetName() */ public function generateAssetNameForCurrentDir($currentDir, array $inputs = array(), array $filters = array(), array $options = array()) { $factory = $this; $flatInputs = array(); array_walk_recursive($inputs, function ($input) use($factory, $currentDir, &$flatInputs) { $flatInputs[] = $factory->normalizeInputForAssetName($input, $currentDir); }); return parent::generateAssetName($flatInputs, $filters, $options); }