/**
  * Adds support for pipeline assets.
  *
  * {@inheritdoc}
  */
 protected function parseInput($input, array $options = array())
 {
     if (is_string($input) && '|' == $input[0]) {
         switch (pathinfo($options['output'], PATHINFO_EXTENSION)) {
             case 'js':
                 $type = 'js';
                 break;
             case 'css':
                 $type = 'css';
                 break;
             default:
                 throw new \RuntimeException('Unsupported pipeline asset type provided: ' . $input);
         }
         $assets = new AssetCollection();
         foreach ($this->locator->locatePipelinedAssets(substr($input, 1), $type) as $formula) {
             $filters = array();
             if ($formula['filter']) {
                 $filters[] = $this->getFilter($formula['filter']);
             }
             $asset = new FileAsset($formula['root'] . '/' . $formula['file'], $filters, $options['root'][0], $formula['file']);
             $asset->setTargetPath($formula['file']);
             $assets->add($asset);
         }
         return $assets;
     }
     return parent::parseInput($input, $options);
 }
 public function testAssetLastModifiedTimestampIsPrependBeforeFileExtension()
 {
     $asset = new FileAsset(TEST_ASSETS_DIR . '/css/global.css');
     $asset->setTargetPath(TEST_PUBLIC_DIR . '/css/global.css');
     $this->cacheBuster->process($asset);
     $this->assertSame(TEST_PUBLIC_DIR . '/css/global.' . $asset->getLastModified() . '.css', $asset->getTargetPath());
 }
 /**
  * {@inheritdoc}
  */
 public function process()
 {
     $filters = new FilterCollection(array(new CssRewriteFilter()));
     $assets = new AssetCollection();
     $styles = $this->packageStyles($this->packages);
     foreach ($styles as $package => $packageStyles) {
         foreach ($packageStyles as $style => $paths) {
             foreach ($paths as $path) {
                 // The full path to the CSS file.
                 $assetPath = realpath($path);
                 // The root of the CSS file.
                 $sourceRoot = dirname($path);
                 // The style path to the CSS file when external.
                 $sourcePath = $package . '/' . $style;
                 // Where the final CSS will be generated.
                 $targetPath = $this->componentDir;
                 // Build the asset and add it to the collection.
                 $asset = new FileAsset($assetPath, $filters, $sourceRoot, $sourcePath);
                 $asset->setTargetPath($targetPath);
                 $assets->add($asset);
             }
         }
     }
     $css = $assets->dump();
     if (file_put_contents($this->componentDir . '/require.css', $css) === FALSE) {
         $this->io->write('<error>Error writing require.css to destination</error>');
         return false;
     }
 }
Exemple #4
0
 protected function createAssetManager()
 {
     $asset = new FileAsset(__DIR__ . '/../../../tests/test.css');
     $asset->setTargetPath('css/test.css');
     $assetManager = new AssetManager();
     $assetManager->set('test_css', $asset);
     return $assetManager;
 }
 public function filterLoad(AssetInterface $asset)
 {
     $importFilter = $this->importFilter;
     $sourceRoot = $asset->getSourceRoot();
     $sourcePath = $asset->getSourcePath();
     $callback = function ($matches) use($importFilter, $sourceRoot, $sourcePath) {
         if (!$matches['url']) {
             return $matches[0];
         }
         if (null === $sourceRoot) {
             return $matches[0];
         }
         $importRoot = $sourceRoot;
         if (false !== strpos($matches['url'], '://')) {
             // absolute
             list($importScheme, $tmp) = explode('://', $matches['url'], 2);
             list($importHost, $importPath) = explode('/', $tmp, 2);
             $importRoot = $importScheme . '://' . $importHost;
         } elseif (0 === strpos($matches['url'], '//')) {
             // protocol-relative
             list($importHost, $importPath) = explode('/', substr($matches['url'], 2), 2);
             $importHost = '//' . $importHost;
         } elseif ('/' == $matches['url'][0]) {
             // root-relative
             $importPath = substr($matches['url'], 1);
         } elseif (null !== $sourcePath) {
             // document-relative
             $importPath = $matches['url'];
             if ('.' != ($sourceDir = dirname($sourcePath))) {
                 $importPath = $sourceDir . '/' . $importPath;
             }
         } else {
             return $matches[0];
         }
         // ignore other imports
         if ('css' != pathinfo($importPath, PATHINFO_EXTENSION)) {
             return $matches[0];
         }
         $importSource = $importRoot . '/' . $importPath;
         if (false !== strpos($importSource, '://') || 0 === strpos($importSource, '//')) {
             $import = new HttpAsset($importSource, array($importFilter), true);
         } elseif (!file_exists($importSource)) {
             // ignore not found imports
             return $matches[0];
         } else {
             $import = new FileAsset($importSource, array($importFilter), $importRoot, $importPath);
         }
         $import->setTargetPath($sourcePath);
         return $import->dump();
     };
     $content = $asset->getContent();
     $lastHash = md5($content);
     do {
         $content = $this->filterImports($content, $callback);
         $hash = md5($content);
     } while ($lastHash != $hash && ($lastHash = $hash));
     $asset->setContent($content);
 }
 /**
  * {@inheritdoc}
  */
 public function process()
 {
     $filters = array(new CssRewriteFilter());
     if ($this->config->has('component-styleFilters')) {
         $customFilters = $this->config->get('component-styleFilters');
         if (isset($customFilters) && is_array($customFilters)) {
             foreach ($customFilters as $filter => $filterParams) {
                 $reflection = new \ReflectionClass($filter);
                 $filters[] = $reflection->newInstanceArgs($filterParams);
             }
         }
     }
     $filterCollection = new FilterCollection($filters);
     $assets = new AssetCollection();
     $styles = $this->packageStyles($this->packages);
     foreach ($styles as $package => $packageStyles) {
         $packageAssets = new AssetCollection();
         $packagePath = $this->componentDir . '/' . $package;
         foreach ($packageStyles as $style => $paths) {
             foreach ($paths as $path) {
                 // The full path to the CSS file.
                 $assetPath = realpath($path);
                 // The root of the CSS file.
                 $sourceRoot = dirname($path);
                 // The style path to the CSS file when external.
                 $sourcePath = $package . '/' . $style;
                 //Replace glob patterns with filenames.
                 $filename = basename($style);
                 if (preg_match('~^\\*(\\.[^\\.]+)$~', $filename, $matches)) {
                     $sourcePath = str_replace($filename, basename($assetPath), $sourcePath);
                 }
                 // Where the final CSS will be generated.
                 $targetPath = $this->componentDir;
                 // Build the asset and add it to the collection.
                 $asset = new FileAsset($assetPath, $filterCollection, $sourceRoot, $sourcePath);
                 $asset->setTargetPath($targetPath);
                 $assets->add($asset);
                 // Add asset to package collection.
                 $sourcePath = preg_replace('{^.*' . preg_quote($package) . '/}', '', $sourcePath);
                 $asset = new FileAsset($assetPath, $filterCollection, $sourceRoot, $sourcePath);
                 $asset->setTargetPath($packagePath);
                 $packageAssets->add($asset);
             }
         }
         if (file_put_contents($packagePath . '/' . $package . '-built.css', $packageAssets->dump()) === FALSE) {
             $this->io->write("<error>Error writing {$package}-built.css to destination</error>");
         }
     }
     if (file_put_contents($this->componentDir . '/require.css', $assets->dump()) === FALSE) {
         $this->io->write('<error>Error writing require.css to destination</error>');
         return false;
     }
     return null;
 }
 public function testAssetWithInputVars()
 {
     $asset = new FileAsset(__DIR__ . '/Fixture/messages.{locale}.js', array(), null, null, array('locale'));
     $asset->setTargetPath('messages.{locale}.js');
     $this->writer->writeAsset($asset);
     $this->assertFileExists($this->dir . '/messages.en.js');
     $this->assertFileExists($this->dir . '/messages.de.js');
     $this->assertFileExists($this->dir . '/messages.fr.js');
     $this->assertEquals('var messages = {"text.greeting": "Hello %name%!"};', file_get_contents($this->dir . '/messages.en.js'));
     $this->assertEquals('var messages = {"text.greeting": "Hallo %name%!"};', file_get_contents($this->dir . '/messages.de.js'));
     $this->assertEquals('var messages = {"text.greet": "All\\u00f4 %name%!"};', file_get_contents($this->dir . '/messages.fr.js'));
 }
 /**
  * @return \Assetic\AssetManager
  */
 protected function createAssetManager()
 {
     $manager = new \Assetic\AssetManager();
     $localeInfo = $this->getLocaleInfo();
     foreach ($localeInfo as $lang => $countries) {
         $manager->set('locale_' . $lang, $asset = new FileAsset(dirname(dirname(__DIR__)) . '/Resources/public/images/' . $lang . '.png'));
         $asset->setTargetPath('images/locale/' . $lang . '.png');
         foreach ($countries as $country) {
             $manager->set('locale_' . $lang . '_' . strtolower($country), $asset = new FileAsset(dirname(dirname(__DIR__)) . '/Resources/public/images/' . $lang . '-' . $country . '.png'));
             $asset->setTargetPath('images/locale/' . $lang . '-' . $country . '.png');
         }
     }
     return $manager;
 }
 public function collectFrameworkStylesheets(CollectAssetsEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
 {
     if (is_array($GLOBALS['TL_FRAMEWORK_CSS']) && !empty($GLOBALS['TL_FRAMEWORK_CSS'])) {
         foreach (array_unique($GLOBALS['TL_FRAMEWORK_CSS']) as $stylesheet) {
             $stripStaticDomainEvent = new StripStaticDomainEvent($event->getRenderMode(), $event->getPage(), $event->getLayout(), $stylesheet);
             $eventDispatcher->dispatch(ThemePlusEvents::STRIP_STATIC_DOMAIN, $stripStaticDomainEvent);
             $stylesheet = $stripStaticDomainEvent->getUrl();
             $asset = new FileAsset(TL_ROOT . DIRECTORY_SEPARATOR . $stylesheet, [new CssRewriteFilter()], TL_ROOT, $stylesheet);
             $generateAssetPathEvent = new GenerateAssetPathEvent($event->getRenderMode(), $event->getPage(), $event->getLayout(), $asset, $event->getDefaultFilters(), 'css');
             $eventDispatcher->dispatch(ThemePlusEvents::GENERATE_ASSET_PATH, $generateAssetPathEvent);
             $asset->setTargetPath($generateAssetPathEvent->getPath());
             $event->append($asset, -50);
         }
         $GLOBALS['TL_FRAMEWORK_CSS'] = [];
     }
 }
 public function cssPackAction()
 {
     $collection = new AssetCollection();
     foreach ($this->container->getParameter('cms.cms_resources.css_pack') as $asset) {
         $assetPath = $this->container->getApplication()->getWebRoot() . DIRECTORY_SEPARATOR . $asset;
         $assetObject = new FileAsset($assetPath, array(), $this->container->getApplication()->getWebRoot());
         $assetObject->setTargetPath('/_cms_internal/');
         if (substr($asset, strrpos($asset, '.')) == '.less') {
             $assetObject->ensureFilter(new LessphpFilter());
         }
         $collection->add($assetObject);
     }
     $content = $this->container->getCache()->fetch('cms_assets', 'css_pack', function () use($collection) {
         return $collection->dump(new CssRewriteFilter());
     }, $collection->getLastModified());
     return new Response($content, 200, array('Content-Type' => 'text/css'));
 }
    /**
     * @dataProvider getFilters
     */
    public function testImport($filter1, $filter2)
    {
        $asset = new FileAsset(__DIR__ . '/fixtures/cssimport/main.css', array(), __DIR__ . '/fixtures/cssimport', 'main.css');
        $asset->setTargetPath('foo/bar.css');
        $asset->ensureFilter($filter1);
        $asset->ensureFilter($filter2);
        $expected = <<<CSS
/* main.css */
/* import.css */
body { color: red; }
/* more/evenmore/deep1.css */
/* more/evenmore/deep2.css */
body {
    background: url(../more/evenmore/bg.gif);
}
body { color: black; }
CSS;
        $this->assertEquals($expected, $asset->dump(), '->filterLoad() inlines CSS imports');
    }
Exemple #12
0
 /**
  * Dump all assets
  */
 public function all()
 {
     foreach ($this->getAssetsXMLFiles() as $path => $XMLFile) {
         $this->out('');
         $this->out(sprintf('<info>Start dumping "%s" assets:</info>', $path));
         $xml = new Xml();
         $domDocument = $xml->build($XMLFile, ['return' => 'domdocument']);
         $xpath = new DOMXPath($domDocument);
         $assetsNodeList = $xpath->query('/assetic/assets/asset');
         $assetManager = new AssetManager();
         /** @var $assetNode DOMElement */
         foreach ($assetsNodeList as $assetNode) {
             $source = strtr($assetNode->getElementsByTagName('source')->item(0)->nodeValue, $this->paths);
             $destination = strtr($assetNode->getElementsByTagName('destination')->item(0)->nodeValue, $this->paths);
             $assetManager->set($assetNode->getAttribute('name'), $fileAsset = new FileAsset($source));
             $fileAsset->setTargetPath($destination);
             $this->out($source . ' <info> >>> </info> ' . WWW_ROOT . $destination);
         }
         $assetWriter = new AssetWriter(WWW_ROOT);
         $assetWriter->writeManagerAssets($assetManager);
         $this->dumpStaticFiles($domDocument);
         $this->out('<info>End</info>');
     }
 }
     }
     if (APP_WEB_SITE_DIR) {
         $writer = new AssetWriter(APP_WEB_SITE_DIR . '/theme/default/img/');
         $writer->writeManagerAssets($am);
     }
     if (APP_WEB_SINGLE_SITE_DIR) {
         $writer = new AssetWriter(APP_WEB_SINGLE_SITE_DIR . '/theme/default/img/');
         $writer->writeManagerAssets($am);
     }
 }
 # Sysadmin
 if (APP_WEB_SYSADMIN_DIR || APP_WEB_SINGLE_SITE_DIR || APP_WEB_INDEX_DIR) {
     $am = new AssetManager();
     foreach ($imgFiles['sysadmin'] as $nameonly => $filename) {
         $fa = new FileAsset($filename, $imgFilters);
         $fa->setTargetPath($nameonly);
         $am->set(str_replace('.', '_', $nameonly), $fa);
     }
     if (APP_WEB_SYSADMIN_DIR) {
         $writer = new AssetWriter(APP_WEB_SYSADMIN_DIR . '/theme/default/imgsysadmin/');
         $writer->writeManagerAssets($am);
     }
     if (APP_WEB_SINGLE_SITE_DIR) {
         $writer = new AssetWriter(APP_WEB_SINGLE_SITE_DIR . '/theme/default/imgsysadmin/');
         $writer->writeManagerAssets($am);
     }
     if (APP_WEB_INDEX_DIR) {
         $writer = new AssetWriter(APP_WEB_INDEX_DIR . '/theme/default/imgsysadmin/');
         $writer->writeManagerAssets($am);
     }
 }
 /**
  * @param string $filename
  * @return FileAsset
  */
 private function getFileAsset($filename)
 {
     $asset = new FileAsset($this->getAssetPath() . $filename);
     $asset->setTargetPath($filename);
     return $asset;
 }
Exemple #15
0
 /**
  * 合并文件,并且返回合并之后的文件名
  *
  * @param  string  $moduleUniqueId
  * @param array    $fileRelativePathArray
  * @param string   $fileExt                     合并之后的文件扩展名
  * @param callback $fileContentFilter           对每个文件的内容做 filter
  *
  * @return string 合并之后的文件名
  */
 private function mergeAssetCssJsFile($moduleUniqueId, array $fileRelativePathArray, $fileExt, $fileContentFilter = null)
 {
     if (empty($fileRelativePathArray)) {
         throw new \InvalidArgumentException('fileRelativePathArray can not be empty');
     }
     $targetModuleBasePath = $this->assetBasePath . DIRECTORY_SEPARATOR . $this->getModulePublishRelativeDir($moduleUniqueId) . DIRECTORY_SEPARATOR;
     // 计算合并之后的文件名
     $targetFileNameSource = '';
     foreach ($fileRelativePathArray as $relativeAssetPath) {
         // 智能发布资源
         $this->publishAsset($moduleUniqueId, $relativeAssetPath);
         $sourcePath = $targetModuleBasePath . $relativeAssetPath;
         if (!is_file($sourcePath)) {
             printLog('Calculate FileNameSource Error : [' . $sourcePath . '] is not a regular file', 'AssetManager', \Core\Log\Base::ERROR);
             continue;
         }
         $targetModifyTime = filemtime($sourcePath);
         $targetFileNameSource .= '{' . $sourcePath . '[' . $targetModifyTime . ']}';
     }
     // 目标文件名
     $targetFileNameSourceMd5 = md5($targetFileNameSource);
     $targetFileName = $targetFileNameSourceMd5 . '.min' . $fileExt;
     // 合并文件已经存在,直接退出就可以了
     if (is_file($targetModuleBasePath . $targetFileName)) {
         goto out;
     }
     // 打印 log
     printLog($targetFileNameSource, 'AssetManager');
     // 做文件的合并
     $filterArray = array();
     // 建立对应的 filter
     if ('.js' == $fileExt) {
         $filterArray = array(new JSMinFilter());
     } elseif ('.css' == $fileExt) {
         $filterArray = array(new CssImportFilter(), new CssRewriteFilter(), new CssMinFilter());
     } else {
         // do nothing
     }
     $mergeFileContent = '';
     foreach ($fileRelativePathArray as $relativeAssetPath) {
         $sourcePath = $targetModuleBasePath . $relativeAssetPath;
         if (!is_file($sourcePath)) {
             printLog('Merge File Error : [' . $sourcePath . '] is not a regular file', 'AssetManager', \Core\Log\Base::ERROR);
             continue;
         }
         // 我们采用 Assetic 来做文件处理
         $fileAsset = new FileAsset($targetModuleBasePath . $relativeAssetPath, $filterArray, $targetModuleBasePath, $relativeAssetPath);
         $fileAsset->setTargetPath('.');
         $mergeFileContent .= $fileContentFilter ? call_user_func_array($fileContentFilter, array($relativeAssetPath, $fileAsset->dump())) : $fileAsset->dump();
         unset($fileAsset);
         // 释放内存
     }
     // 生成合并之后的文件
     file_put_contents($targetModuleBasePath . $targetFileName, $mergeFileContent);
     out:
     return $targetFileName;
 }
 public function testWriteAssetIfNotUpdated()
 {
     $this->configuration->setBuildOnRequest(true);
     $this->configuration->setWriteIfChanged(true);
     $this->object->build();
     $manager = $this->object->getAssetManager();
     $assets = $manager->get('base_css')->all();
     /** @var \Assetic\Asset\AssetInterface $asset */
     $asset = $assets[0];
     $asset->setTargetPath($manager->get('base_css')->getTargetPath());
     $targetFile = $this->configuration->getWebPath($asset->getTargetPath());
     if (is_file($targetFile)) {
         unlink($targetFile);
     }
     $this->assertFileNotExists($targetFile);
     $this->object->writeAsset($asset);
     $this->assertFileExists($targetFile);
     $sourceFile = $asset->getSourceRoot() . '/' . $asset->getSourcePath();
     $targetMTime = filemtime($targetFile);
     sleep(2);
     $modifiedAsset = new FileAsset($sourceFile);
     $modifiedAsset->setTargetPath($targetFile);
     $this->object->writeAsset($modifiedAsset);
     clearstatcache(true, $targetFile);
     $targetMTimeNotModified = filemtime($targetFile);
     $this->assertLessThanOrEqual($targetMTime, $targetMTimeNotModified);
 }
Exemple #17
0
 protected function addStyleSheets($objPage, $objLayout, array $files, $path, $useSass, array $filters)
 {
     /** @var RenderModeDeterminer $renderModeDeterminer */
     $renderModeDeterminer = $GLOBALS['container']['theme-plus-render-mode-determiner'];
     $renderMode = $renderModeDeterminer->determineMode();
     /** @var AsseticFactory $asseticFactory */
     $asseticFactory = $GLOBALS['container']['assetic.factory'];
     // default filter
     $defaultFilters = $asseticFactory->createFilterOrChain($objLayout->asseticStylesheetFilter, RenderMode::DESIGN == $renderMode);
     /** @var EventDispatcherInterface $eventDispatcher */
     $eventDispatcher = $GLOBALS['container']['event-dispatcher'];
     foreach ($files as $file) {
         if ($useSass) {
             $file = $this->transformCssToSass($file);
         }
         $file = $path . '/' . $file;
         $asset = new FileAsset(TL_ROOT . '/' . $file, $filters, TL_ROOT, $file);
         $generateAssetPathEvent = new GenerateAssetPathEvent($renderMode, $objPage, $objLayout, $asset, $defaultFilters, 'css');
         $eventDispatcher->dispatch(ThemePlusEvents::GENERATE_ASSET_PATH, $generateAssetPathEvent);
         $asset->setTargetPath($generateAssetPathEvent->getPath());
         array_unshift($GLOBALS['TL_CSS'], $asset);
     }
 }