{"action":"closed","issue":{"url":"https://api.github.com/repos/symfony/symfony/issues/21660","repository_url":"https://api.github.com/repos/symfony/symfony","labels_url":"https://api.github.com/repos/symfony/symfony/issues/21660/labels{/name}","comments_url":"https://api.github.com/repos/symfony/symfony/issues/21660/comments","events_url":"https://api.github.com/repos/symfony/symfony/issues/21660/events","html_url":"https://github.com/symfony/symfony/issues/21660","id":208650122,"number":21660,"title":"Voter priority in reverse order from lowest to highest","user":{"login":"scoolen","id":522523,"avatar_url":"https://avatars.githubusercontent.com/u/522523?v=3","gravatar_id":"","url":"https://api.github.com/users/scoolen","html_url":"https://github.com/scoolen","followers_url":"https://api.github.com/users/scoolen/followers","following_url":"https://api.github.com/users/scoolen/following{/other_user}","gists_url":"https://api.github.com/users/scoolen/gists{/gist_id}","starred_url":"https://api.github.com/users/scoolen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scoolen/subscriptions","organizations_url":"https://api.github.com/users/scoolen/orgs","repos_url":"https://api.github.com/users/scoolen/repos","events_url":"https://api.github.com/users/scoolen/events{/privacy}","received_events_url":"https://api.github.com/users/scoolen/received_events","type":"User","site_admin":false},"labels":[{"id":100079,"url":"https://api.github.com/repos/symfony/symfony/labels/Bug","name":"Bug","color":"e10c02","default":false},{"id":99600,"url":"https://api.github.com/repos/symfony/symfony/labels/Security","name":"Security","color":"DDDDDD","default":false},{"id":237003792,"url":"https://api.github.com/repos/symfony/symfony/labels/Status:%20Needs%20Review","name":"Status: Needs Review","color":"ededed","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2017-02-18T15:57:39Z","updated_at":"2017-02-22T02:40:16Z","closed_at":"2017-02-22T02:40:16Z","body":"| Q                | A\r\n| ---------------- | -----\r\n| Bug report?      | yes\r\n| Feature request? | no\r\n| BC Break report? | no\r\n| RFC?             | no\r\n| Symfony version  | v2.8.11\r\n\r\nAlthough this is poorly documented, I understand that voter services can have a priority.\r\n\r\nRelevant commit: https://github.com/symfony/symfony/commit/0643dc44fddf347f4ffdc5764b141bfadc54aeb8\r\n\r\nSimilar to other DI tags with a priority attribute this was intended to be implemented as follows:\r\n\r\n> The priority value is optional and defaults to 0. The higher the priority, the sooner it gets executed.\r\n\r\nThe compiler pass responsible for adding all configured voters is the [AddSecurityVoterPass](https://github.com/symfony/symfony/blob/v2.8.11/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php) which uses an SplPriorityQueue (max heap) to correctly order the voters one by one.\r\n\r\nThe priority queue is then converted to an array and passed to the AccessDecissionManager service definition by adding a method call for ``setVoters``.\r\n\r\nThe problem is that right after the array conversion a [ksort](http://php.net/manual/en/function.ksort.php) is done on the voters array. **This actually reverses the prioritization done by SplPriorityQueue!**\r\n\r\nResult: voters are ordered from lowest to highest priority and are also processed in this order in the different decision strategies.\r\n\r\nI think the priority queue was added later as an optimization for setting the prio as the indices of an associative array, but the obsolete call to ksort was never removed.\r\n\r\nI double checked other compiler passes using priority attributes:\r\n\r\n| Compiler Pass         | A-OK  | unit tested | impl\r\n| --------------------- | ----- | ----------- | ----\r\n| AddCacheWarmerPass    | yes   | yes         | set + ksort\r\n| AddSecurityVotersPass | no    | **no**      | prio queue + ksort\r\n| ConfigCachePass       | yes   | yes         | set + ksort\r\n| ProfilerPass          | yes   | **no**      | prio queue\r\n| PropertyInfoPass      | yes   | yes         | set + ksort\r\n| SerializerPass        | yes   | yes         | set + ksort\r\n\r\n"}}
{"actor":{"display_login":"fabpot"}}