Skip to content

[2.2] ResourceWatcher component (final?) #4605

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

Closed
wants to merge 69 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
f4f97fe
[ResourceWatcher] resource change event created
everzet Mar 25, 2011
f543d35
[ResourceWatcher] resource event listener interface described
everzet Mar 25, 2011
5173ca3
[ResourceWatcher] created basic resource event listener object
everzet Mar 25, 2011
5cb04ad
[ResourceWatcher] resource state checker interface described
everzet Mar 25, 2011
8e840e7
[ResourceWatcher] created recursive iterator resource state checker
everzet Mar 25, 2011
efd9465
[ResourceWatcher] resources tracker interface described
everzet Mar 25, 2011
9c8eb16
[ResourceWatcher] recursive iterator resources tracker created
everzet Mar 25, 2011
c0ee08e
[ResourceWatcher] resource watcher object created
everzet Mar 25, 2011
42ee8de
[ResourceWatcher] inotify tracker added
everzet Mar 25, 2011
f84133b
[ResourceWatcher] use best tracker by default
everzet Mar 25, 2011
3df1211
[ResourceWatcher] renamed Event::handes to Event::supports to be cons…
everzet Mar 25, 2011
346a23e
[ResourceWatcher] fixed non-empty directory events
everzet Aug 20, 2011
7a1b9e4
[Config] updated resources API to be more explicit
everzet Nov 19, 2011
0e0e842
[Config] moved DirectoryResource childs retrieving to the special get…
everzet Nov 19, 2011
703e450
[ResourceWatcher] cleaned code little bit
everzet Nov 19, 2011
8919d63
[ResourceWatcher] refactored recursive state checkers into 2 separate…
everzet Nov 19, 2011
9077500
[Config] getFilteredChildResources() method added to DirectoryResource
everzet Nov 19, 2011
d9de08f
[ResourceWatcher] refactored recursive iterator tracker to support ne…
everzet Nov 19, 2011
38638a7
[Config] updated DirectoryResource tests
everzet Nov 25, 2011
2acc262
[Config] update FileResourceTest
everzet Nov 25, 2011
44dd464
[ResourceWatcher] removed InotifyTracker as i have no ability to test…
everzet Nov 25, 2011
7413969
[Config] added new methods and their tests to File and Directory reso…
everzet Nov 29, 2011
54cc762
[ResourceWatcher] updated ResourceWatcher and TrackerInterface
everzet Nov 29, 2011
79cfe58
[ResourceWatcher] added time information to events
everzet Nov 29, 2011
fecdfc9
[ResourceWatcher] updated FileStateChecker to match FileResource API
everzet Nov 29, 2011
079fa44
[ResourceWatcher] refactored DirectoryStateChecker
everzet Nov 29, 2011
17da838
[ResourceWatcher] refactored RecursiveIteratorTracker
everzet Nov 29, 2011
8f7097a
[ResourceWatcher] updated StateCheckerInterface
everzet Nov 29, 2011
c05c02f
[ResourceWatcher] return of the InotifyTracker
everzet Nov 29, 2011
83ec92d
[ResourceWatcher] removed unneeded code
fabpot Dec 5, 2011
3f7d471
[ResourceWatcher] added an exception when inotify is not available
fabpot Dec 5, 2011
869d070
[Config] made ResourceInterface extends Serializable
fabpot Dec 5, 2011
4c9d239
[ResourceWatcher] removed dead code
fabpot Dec 5, 2011
6ea1116
[ResourceWatcher] added the possibility to watch files that do not ex…
fabpot Dec 5, 2011
50360c2
[ResourceWatcher] added exception classes for the component
fabpot Dec 29, 2011
ac7f8b9
-
fabpot Dec 29, 2011
cfee37a
[ResourceWatcher] moved tests into component folder
everzet Apr 7, 2012
9c8c7aa
[ResourceWatcher] refactored event subsystem
everzet Apr 16, 2012
8351c8d
[ResourceWatcher] added TrackedResource class
everzet Apr 16, 2012
fded799
[ResourceWatcher] refactored ResourceWatcher
everzet Apr 16, 2012
6d1de0a
[ResourceWatcher] refactored TrackerInterface
everzet Apr 16, 2012
a4bd989
[ResourceWatcher] refactored RecursiveIteratorTracker to support new …
everzet Apr 16, 2012
a1b88a1
[ResourceWatcher] added support for events mask in ResourceStateChecker
everzet Apr 16, 2012
9de24c6
[ResourceWatcher] refactored state checkers to support new interfaces…
everzet Apr 16, 2012
d3e85a0
[ResourceWatcher] refactored TrackerTest and added missing test cases
everzet Apr 16, 2012
ff309a5
[ResourceWatcher] added missing TrackerTest cases
everzet Apr 16, 2012
111990f
[ResourceWatcher] optimized TrackerTest cases
everzet Apr 16, 2012
1d17da7
[ResourceWatcher] started InotifyTracker refactoring
everzet Apr 16, 2012
77ebe0c
[ResourceWatcher] cleaned ResourceWatcher API to be more consistent w…
everzet Apr 16, 2012
7a10e7b
[ResourceWatcher] fixed intofiy function call
everzet Apr 17, 2012
5d7525a
[Config] skip dots in getFilteredChilds() (fixes test suite on Linux)
everzet Apr 20, 2012
c591de8
[ResourceWatcher] removed InotifyTracker as it was not finished anywa…
everzet Apr 20, 2012
09af8bd
[ResourceWatcher] added functional test for ResourceWatcher class
everzet Apr 20, 2012
d236e5c
[ResourceWatcher] prevent temp folder flooding by test suite
everzet Apr 20, 2012
70871b3
[ResourceWatcher] Inotify Tracker.
Dattaya May 24, 2012
ac2c871
[ResourceWatcher] Typos, docblock clear.
Dattaya May 24, 2012
d30de16
[ResourceWatcher] DirectoryStateCheckerTest, onConsecutiveCalls issue.
Dattaya May 24, 2012
5b42fcf
Moved previously added assertions from `testTrackDeepDirChanges` to t…
Dattaya May 26, 2012
b53dd92
[ResourceWatcher] NewDirectoryStateChecker: removed unnecessary `$re…
Dattaya May 27, 2012
c5724e7
[ResourceWatcher] Ran CS Fixer against code + fixed some CS issues by…
Dattaya May 27, 2012
3102e21
[Config] added type prefixes to resource ids
everzet Jun 9, 2012
64cecb6
[Config] use is_file in FileResource::exists()
everzet Jun 9, 2012
beda449
[ResourceWatcher] ResourceWatcher functional test, small addition.
Dattaya Jun 13, 2012
39f829e
[ResourceWatcher] Get rid of FilesystemEvent events' "IN_" prefix.
Dattaya Jun 13, 2012
f34669a
[ResourceWatcher] added composer configuration
everzet Jun 13, 2012
480c270
added symfony/config as resource watcher dependency
everzet Jun 13, 2012
9699c30
added ext-inotify to suggest block
everzet Jun 18, 2012
b2f0704
[ResourceWatcher] added event dispatcher as dependency
everzet Jun 18, 2012
d1a7fcb
[ResourceWatcher] added missing contributors
everzet Jun 18, 2012
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"symfony/browser-kit": "self.version",
"symfony/class-loader": "self.version",
"symfony/config": "self.version",
"symfony/resource-watcher": "self.version",
"symfony/console": "self.version",
"symfony/css-selector": "self.version",
"symfony/dependency-injection": "self.version",
Expand Down
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
*/
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