Skip to content

[Config] additions from ResourceWatcher #4619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jun 20, 2012
165 changes: 148 additions & 17 deletions src/Symfony/Component/Config/Resource/DirectoryResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DirectoryResource implements ResourceInterface, \Serializable
class DirectoryResource implements ResourceInterface
{
private $resource;
private $pattern;
Expand All @@ -33,6 +33,82 @@ public function __construct($resource, $pattern = null)
$this->pattern = $pattern;
}

/**
* Returns the list of filtered file and directory childs of directory resource.
*
* @return array An array of files
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ return should be FilesystemIterator[] as its an array of FilesystemIterator objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sstok no, it's an array in any case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, wait. You mean using FilesystemIterator[] as description to array of FilesystemIterator? This sounds even crazier than old good docblocks now :) @fabpot @stof what do you think, guys? I'm not sure we stick to this @... ...[] convention in Symfony2, do we?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a large number of Components that us it :) Templating, Translator, Config, Console, DepencyInjection, Routing, Security.

Use this regex @(return|param)\s+[\w\d]+\[\] to search there usage.

*/
public function getFilteredChilds()
{
if (!$this->exists()) {
return array();
}

$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($this->resource, \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::SELF_FIRST
);

$childs = array();
foreach ($iterator as $file) {
// if regex filtering is enabled only return matching files
if ($file->isFile() && !$this->hasFile($file)) {
continue;
}

// always monitor directories for changes, except the .. entries
// (otherwise deleted files wouldn't get detected)
if ($file->isDir() && '/..' === substr($file, -3)) {
continue;
}

$childs[] = $file;
}

return $childs;
}

/**
* Returns child resources that matches directory filters.
*
* @return array
*/
public function getFilteredResources()
{
if (!$this->exists()) {
return array();
}

$iterator = new \DirectoryIterator($this->resource);

$resources = array();
foreach ($iterator as $file) {
// if regex filtering is enabled only return matching files
if ($file->isFile() && !$this->hasFile($file)) {
continue;
}

// always monitor directories for changes, except the .. entries
// (otherwise deleted files wouldn't get detected)
if ($file->isDir() && '/..' === substr($file, -3)) {
continue;
}

// if file is dot - continue
if ($file->isDot()) {
continue;
}

if ($file->isFile()) {
$resources[] = new FileResource($file->getRealPath());
} elseif ($file->isDir()) {
$resources[] = new DirectoryResource($file->getRealPath());
}
}

return $resources;
}

/**
* Returns a string representation of the Resource.
*
Expand All @@ -53,11 +129,62 @@ public function getResource()
return $this->resource;
}

/**
* Returns check pattern.
*
* @return mixed
*/
public function getPattern()
{
return $this->pattern;
}

/**
* Checks that passed file exists in resource and matches resource filters.
*
* @param SplFileInfo|string $file
*
* @return Boolean
*/
public function hasFile($file)
{
if (!$file instanceof \SplFileInfo) {
$file = new \SplFileInfo($file);
}

if (0 !== strpos($file->getRealPath(), realpath($this->resource))) {
return false;
}

if ($this->pattern) {
return (bool) preg_match($this->pattern, $file->getBasename());
}

return true;
}

/**
* Returns resource mtime.
*
* @return integer
*/
public function getModificationTime()
{
if (!$this->exists()) {
return -1;
}

clearstatcache(true, $this->resource);
$newestMTime = filemtime($this->resource);

foreach ($this->getFilteredChilds() as $file) {
clearstatcache(true, (string) $file);
$newestMTime = max($file->getMTime(), $newestMTime);
}

return $newestMTime;
}

/**
* Returns true if the resource has not been updated since the given timestamp.
*
Expand All @@ -67,27 +194,31 @@ public function getPattern()
*/
public function isFresh($timestamp)
{
if (!is_dir($this->resource)) {
if (!$this->exists()) {
return false;
}

$newestMTime = filemtime($this->resource);
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) {
// if regex filtering is enabled only check matching files
if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) {
continue;
}

// always monitor directories for changes, except the .. entries
// (otherwise deleted files wouldn't get detected)
if ($file->isDir() && '/..' === substr($file, -3)) {
continue;
}
return $this->getModificationTime() < $timestamp;
}

$newestMTime = max($file->getMTime(), $newestMTime);
}
/**
* Returns true if the resource exists in the filesystem.
*
* @return Boolean
*/
public function exists()
{
return is_dir($this->resource);
}

return $newestMTime < $timestamp;
/**
* Returns unique resource ID.
*
* @return string
*/
public function getId()
{
return md5('d'.$this->resource.$this->pattern);
}

public function serialize()
Expand Down
44 changes: 40 additions & 4 deletions src/Symfony/Component/Config/Resource/FileResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class FileResource implements ResourceInterface, \Serializable
class FileResource implements ResourceInterface
{
private $resource;

Expand All @@ -29,7 +29,7 @@ class FileResource implements ResourceInterface, \Serializable
*/
public function __construct($resource)
{
$this->resource = realpath($resource);
$this->resource = file_exists($resource) ? realpath($resource) : $resource;
}

/**
Expand All @@ -52,6 +52,22 @@ public function getResource()
return $this->resource;
}

/**
* Returns resource mtime.
*
* @return integer
*/
public function getModificationTime()
{
if (!$this->exists()) {
return -1;
}

clearstatcache(true, $this->resource);

return filemtime($this->resource);
}

/**
* Returns true if the resource has not been updated since the given timestamp.
*
Expand All @@ -61,11 +77,31 @@ public function getResource()
*/
public function isFresh($timestamp)
{
if (!file_exists($this->resource)) {
if (!$this->exists()) {
return false;
}

return filemtime($this->resource) < $timestamp;
return $this->getModificationTime() <= $timestamp;
}

/**
* Returns true if the resource exists in the filesystem.
*
* @return Boolean
*/
public function exists()
{
return is_file($this->resource);
}

/**
* Returns unique resource ID.
*
* @return string
*/
public function getId()
{
return md5('f'.$this->resource);
}

public function serialize()
Expand Down
23 changes: 22 additions & 1 deletion src/Symfony/Component/Config/Resource/ResourceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface ResourceInterface
interface ResourceInterface extends \Serializable
{
/**
* Returns a string representation of the Resource.
Expand All @@ -34,10 +34,31 @@ function __toString();
*/
function isFresh($timestamp);

/**
* Returns resource mtime.
*
* @return integer
*/
function getModificationTime();

/**
* Returns true if the resource exists in the filesystem.
*
* @return Boolean
*/
function exists();

/**
* Returns the resource tied to this Resource.
*
* @return mixed The resource
*/
function getResource();

/**
* Returns unique resource ID.
*
* @return string
*/
function getId();
}
Loading