{"action":"closed","issue":{"url":"https://api.github.com/repos/symfony/symfony/issues/7176","labels_url":"https://api.github.com/repos/symfony/symfony/issues/7176/labels{/name}","comments_url":"https://api.github.com/repos/symfony/symfony/issues/7176/comments","events_url":"https://api.github.com/repos/symfony/symfony/issues/7176/events","html_url":"https://github.com/symfony/symfony/issues/7176","id":11356734,"number":7176,"title":"[Config] RFC - Simplify and redesign ResourceInterface","user":{"login":"mpdude","id":1202333,"avatar_url":"https://avatars.githubusercontent.com/u/1202333?v=3","gravatar_id":"","url":"https://api.github.com/users/mpdude","html_url":"https://github.com/mpdude","followers_url":"https://api.github.com/users/mpdude/followers","following_url":"https://api.github.com/users/mpdude/following{/other_user}","gists_url":"https://api.github.com/users/mpdude/gists{/gist_id}","starred_url":"https://api.github.com/users/mpdude/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mpdude/subscriptions","organizations_url":"https://api.github.com/users/mpdude/orgs","repos_url":"https://api.github.com/users/mpdude/repos","events_url":"https://api.github.com/users/mpdude/events{/privacy}","received_events_url":"https://api.github.com/users/mpdude/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/symfony/symfony/labels/Config","name":"Config","color":"DDDDDD"},{"url":"https://api.github.com/repos/symfony/symfony/labels/Feature","name":"Feature","color":"02e10c"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2013-02-25T12:23:49Z","updated_at":"2015-10-05T10:54:48Z","closed_at":"2015-10-05T10:54:48Z","body":"Currently, [Config/ResourceInterface](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Config/Resource/ResourceInterface.php) and its implementations serve a single purpose - that is, checking whether data from a ConfigCache is still valid. For that, the cache is associated with a set of Resources which can later be checked for freshness. ConfigCache seems to be the only client of ResourceInterface right now.\r\n\r\nThe problem with the interface is that it somewhat assumes that resources are filesystem objects. Just as Loaders (Config/Loader/LoaderInterface) can load about anything, the same should be true for Resources.\r\n\r\nFor example, it is no problem to have a loader pull some information (think of translations) from a database. At a later time, you might need to check if the generated message catalogue is still up to date.\r\n\r\nImplementing ResourceInterface in this case is difficult - __toString() and getResource() hardly make sense for \"translations from a database\", and at least to getResource() is the Loader's job. Anyway, both methods are not used by ConfigCache as the current sole client. \r\n\r\n__Freshness check based on timestamp__\r\n\r\nChecking isFresh($timestamp) - which means \"is the Resource still the same as it was at $timestamp\" - might also be implemented differently for the said database. \r\n\r\nThe $timestamp need not be a timestamp but just an opaque identifier (think ETag). Even more, as Resource implementations being serialized carry resource type-specific data anyway (a filename, for example), the entire way of validating them should be encapsulated in the Resource. That is, a Resource could upon creation get or keep what it needs for validation. \r\nFor example, a FileResource would grab the mtime() of the underlying file, keep it along with the filename (in its serialized form) and later on (when unserialized) check the mtime() again, comparing the two values.\r\n\r\n__A more simple, self-validating Resource interface__\r\n\r\nAll this would lead to a ResourceInterface like\r\n\r\n````\r\nnamespace Symfony\\Component\\Config\\Resource;\r\n\r\ninterface ResourceInterface\r\n{\r\n    /**\r\n     * Returns true if the resource has been updated since it has been created.\r\n     * @return Boolean true if the resource haseen updated, false otherwise\r\n     */\r\n    public function hasChanged();\r\n}\r\n\r\n````\r\n*plus* the requirement the implementors are (un)serializable without side effects.\r\n\r\n__Resource checks using services__\r\n\r\nI also [made a suggestion](https://github.com/symfony/AsseticBundle/issues/168#issuecomment-13608074) how  Resource validation could be shifted from the Resource implementation to some kind of \"voter\" or \"checker\" class which allows for using services (a database connection, a loader implementation) during the check which is not possible if the check has to be within the unserialized resource.\r\n\r\nThat would even leave Resource as a marker interface and have the \"voter\" implement a single \"hasChanged(Resource $r)\" method.\r\n\r\n__To sum up__\r\n\r\nI think simplifying the ResourceInterface would be a good thing to do because\r\n* it adds conceptual clarity\r\n* yields a segregated interface\r\n* allows for new Resource types that can reflect what loaders can already do\r\n\r\nShifting the freshness check from Resource implementations to some kind of \"voter\"/\"checker\" additionally makes it possible to use services for validation, being a solution for [at least one issue](https://github.com/symfony/AsseticBundle/issues/168).\r\n\r\nOpinions please. Will do the work if others agree :-).\r\n\r\n__Update__: The current WIP is #7230."}}