Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandresalome committed Sep 22, 2013
0 parents commit b9a29b3
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/vendor/
/composer.lock

5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
language: php
before_script:
- composer install
php:
- 5.3
9 changes: 9 additions & 0 deletions AlexAsseticExtraBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Alex\AsseticExtraBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class AlexAsseticExtraBundle extends Bundle
{
}
66 changes: 66 additions & 0 deletions Assetic/Filter/AssetDirectoryFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Alex\AsseticExtraBundle\Assetic\Filter;

use Alex\AsseticExtraBundle\Assetic\Util\AssetDirectory;
use Alex\AsseticExtraBundle\Assetic\Util\PathUtils;
use Assetic\Asset\AssetInterface;
use Assetic\Filter\BaseCssFilter;

/**
* Parses URLs in a CSS and move all assets to a folder,
* changing location of them in CSS.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class AssetDirectoryFilter extends BaseCssFilter
{
/**
* @var AssetDirectory
*/
protected $directory;

/**
* @param AssetDirectory $directory directory where to store assets
*/
public function __construct(AssetDirectory $directory)
{
$this->directory = $directory;
}

/**
* {@inheritdoc}
*/
public function filterLoad(AssetInterface $asset)
{
}

/**
* {@inheritdoc}
*/
public function filterDump(AssetInterface $asset)
{
$directory = $this->directory;

if (null === $asset->getSourcePath() || null === $asset->getTargetPath()) {
return;
}

$content = $this->filterReferences($asset->getContent(), function ($matches) use ($asset, $directory) {
$url = $matches['url'];

if (false !== strpos($url, '://')) {
return $matches[0];
}

$file = PathUtils::resolveUrl($asset, $url);
$target = $this->directory->add($file);

$path = PathUtils::resolveRelative($target, $asset->getTargetPath()).basename($file);

return str_replace($matches['url'], $path, $matches[0]);
});

$asset->setContent($content);
}
}
170 changes: 170 additions & 0 deletions Assetic/Util/AssetDirectory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php

namespace Alex\AsseticExtraBundle\Assetic\Util;

use Assetic\Cache\CacheInterface;

/**
* Class to interact with a folder containing images.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class AssetDirectory
{
/**
* @var string
*/
protected $directory;

/**
* @var string
*/
protected $target;

/**
* @var CacheInterface
*/
protected $cache;

/**
* Constructs a new asset directory
*
* @param string $directory path to the directory of assets
* @param CacheInterface $cache a cache to use, to avoid copying the same file
*/
public function __construct($directory, $target = null, CacheInterface $cache = null)
{
$this->directory = $directory;
$this->target = $target;
$this->cache = $cache;
}

/**
* Copy a file to the directory.
*
* @param string $file fullpath of file to add
* @param boolean $force ignore cache and add file to directory
*
* @throws InvalidArgumentException file does not exist
* @throws RuntimeException filesystem errors
*
* @return string target image path
*/
public function add($file, $force = false)
{
if (!file_exists($file)) {
throw new \InvalidArgumentException(sprintf('File "%s" does not exist.', $file));
}

if (false === $force && null !== $path = $this->getCache($file)) {
return null === $this->target ? $path : $this->target.'/'.$path;
}

$name = $this->findAvailableName($file);

if (null !== $this->cache) {
$this->cache->set(md5($file), serialize(array(filemtime($file), $name)));
}

if (!is_dir($dir = dirname($target = $this->directory.'/'.$name))) {
mkdir($dir, 0777, true);
}

if (false === @copy($file, $target)) {
throw new \RuntimeException(sprintf('Error while copying "%s" to "%s".', $file, $target));
}

return null === $this->target ? $name : $this->target.'/'.$name;
}

/**
* Returns directory.
*
* @return string
*/
public function getDirectory()
{
return $this->directory;
}

/**
* Returns target.
*
* @return string
*/
public function getTarget()
{
return $this->target;
}

/**
* Changes target value.
*
* @param string $target a target path
*
* @return AssetDirectory fluid interface
*/
public function setTarget($target)
{
$this->target = $target;

return $this;
}

/**
* Searches a fresh cached file for the given file.
*
* @throws RuntimeException filesystem errors
*/
private function getCache($file)
{
if (null === $this->cache) {
return null;
}

$key = md5($file);

// File already present
if ($this->cache->has($key)) {
list($mtime, $path) = unserialize($this->cache->get($key));

if ($mtime === filemtime($file)) {
return $path;
}

$delete = $this->directory.'/'.$path;
if (file_exists($delete) && false === @unlink($delete)) {
throw new \RuntimeException('Unable to remove file '.$delete);
}
}

return null;
}

/**
* Finds a name not used, incrementing if file already
* exists in storage : foo.png, foo_1.png, foo_2.png...
*
* @return string a relative path
*/
private function findAvailableName($file)
{
$name = basename($file);

if (!file_exists($this->directory.'/'.$name)) {
return $name;
}

$dotPos = strrpos($name, '.');
$prefix = substr($name, 0, $dotPos);
$suffix = substr($name, $dotPos);

$count = 1;
do {
$name = $prefix.'_'.$count.$suffix;
$count++;
} while (file_exists($this->directory.'/'.$name));

return $name;
}
}
Loading

0 comments on commit b9a29b3

Please sign in to comment.