├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE-CC.md ├── LICENSE-MIT.md ├── LICENSE.md ├── README.md ├── accepted ├── PSR-0.md ├── PSR-1-basic-coding-standard.md ├── PSR-11-container-meta.md ├── PSR-11-container.md ├── PSR-12-extended-coding-style-guide-meta.md ├── PSR-12-extended-coding-style-guide.md ├── PSR-13-links-meta.md ├── PSR-13-links.md ├── PSR-14-event-dispatcher-meta.md ├── PSR-14-event-dispatcher.md ├── PSR-15-request-handlers-meta.md ├── PSR-15-request-handlers.md ├── PSR-16-simple-cache-meta.md ├── PSR-16-simple-cache.md ├── PSR-17-http-factory-meta.md ├── PSR-17-http-factory.md ├── PSR-18-http-client-meta.md ├── PSR-18-http-client.md ├── PSR-2-coding-style-guide-meta.md ├── PSR-2-coding-style-guide.md ├── PSR-3-logger-interface-meta.md ├── PSR-3-logger-interface.md ├── PSR-4-autoloader-examples.md ├── PSR-4-autoloader-meta.md ├── PSR-4-autoloader.md ├── PSR-6-cache-meta.md ├── PSR-6-cache.md ├── PSR-7-http-message-meta.md └── PSR-7-http-message.md ├── bylaws ├── 001-mission-and-structure.md ├── 002-psr-workflow.md ├── 003-per-workflow.md ├── 004-votes.md ├── 005-elections-and-vacancies.md ├── 006-licensing-policies.md ├── 007-psr-amendments.md ├── 008-psr-evolution.md ├── 009-naming-conventions.md └── 100-implementation.md ├── index.md ├── personnel.md └── proposed ├── .placeholder ├── clock-meta.md ├── clock.md ├── phpdoc-meta.md ├── phpdoc-tags-meta.md ├── phpdoc-tags.md ├── phpdoc.md ├── psr-8-hug ├── PSR-8-hug-meta.md └── psr-8-hug.md ├── security-disclosure-publication-meta.md ├── security-disclosure-publication.md ├── security-disclosure-publication.xsd ├── security-reporting-process-meta.md └── security-reporting-process.md /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @php-fig/secretaries 2 | /proposed/security* @php-fig/psr-9-10 3 | /proposed/phpdoc* @php-fig/psr-5 4 | /proposed/clock* @php-fig/psr-20 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the PHP-FIG 2 | 3 | Anybody who subscribes to the Google Group, is part of the PHP-FIG. As soon as 4 | you subscribe to the [mailing list](http://groups.google.com/group/php-fig/) 5 | and/or join the [IRC channel](https://www.php-fig.org/irc/) you are a PHP-FIG 6 | Community Member, who can influence standards, make suggestions, give feedback, 7 | etc. Only PHP-FIG Voting Members can start or participate in votes, but the 8 | discussion and formation stages involve everyone. 9 | 10 | See the [PHP-FIG FAQ](https://www.php-fig.org/faqs/) for more information. 11 | 12 | # Licensing 13 | 14 | By contributing code you agree to license your contribution under the MIT 15 | license. 16 | 17 | By contributing documentation, examples, or any other non-code assets you agree 18 | to license your contribution under the CC BY 3.0 license. Attribution shall be 19 | given according to the current bylaws of this group. 20 | 21 | # Merge & Access Policy 22 | 23 | All Editors, Coordinators and Sponsors of specifications in draft & review stage 24 | have access to push to this (php-fig/fig-standards) repository; subject to 25 | secretary discretion 26 | 27 | All Editors, Coordinators and Sponsors of specifications have push access to utility 28 | and interface repositories and retrain this even after acceptance; subject to secretary 29 | discretion. 30 | 31 | The master branch of all repositories are protected and therefore cannot be forced 32 | pushed to. 33 | 34 | Secretaries have, and are the only ones to have, full administrative access to all 35 | repositories and to the github organisation. 36 | 37 | ## Guidelines for merging 38 | 39 | * Never force push to any branch on a repository in the php-fig organisation 40 | * All changes must go through pull requests, a commit should never be pushed 41 | directly (excluding initial commits on new interface/util repositories) to master 42 | * All pull requests relating to a draft PSR must be approved (with a formal +1 43 | comment) or merged by the PSR Editor, except in the review phase when the coordinator 44 | should seek comment from the editor, but merging is at the coordinator's discretion 45 | * You must never merge a pull request that affects any file in the repository 46 | other than those you are on a working group for; you should request a secretary 47 | or member of that working group (mention @php-fig/psr-x) do so 48 | * You should never merge your own pull request 49 | * A change should never be merged to an accepted PSR without approval from 50 | secretaries, who will attempt to seek confirmation from the former Editors 51 | * A change to bylaws shouldn't be merged by anyone other than a secretary 52 | * Pull requests may be triaged (have labels applied) by anyone with push access, 53 | no matter which PSR they are on the working group for or which PSR it affects; but 54 | they cannot close a pull request or issue affecting other PSRs 55 | * After approval of a specification, all merges to an interface or utility repository 56 | must be approved by a secretary; who is required to give suitable notice and seek 57 | comment from the working group team, but it is not required that they approve 58 | * Tags on utility and interface repositories should be created and PGP signed by 59 | Secretaries, who should publish their PGP public keys and register them on github 60 | 61 | These guidelines are subject to exceptions and changes at secretaries discretion. 62 | Should you have any questions please contact the secretaries on info [at] php-fig 63 | [dot] org. Failure to comply with guidelines will result in revokation of merge 64 | access. Merge access is a privilege and not a right. 65 | 66 | # Tagging 67 | 68 | Tagging on utility and interface repository should be done regularly, ideally after 69 | every merge, or every batch of merges after PSR approval. 70 | 71 | Versioning should follow semantic versioning and primarily just be simple patch 72 | fix increments (following semantic versioning). The first 1.0.0 tag should be 73 | created on PSR approval. 74 | 75 | All tags should be PGP signed. 76 | 77 | A changelog should be provided including a list of changes, crediting the 78 | contributor and referencing the pull request/issue. 79 | -------------------------------------------------------------------------------- /LICENSE-MIT.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2017 PHP Framework Interop Group 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Unless stated otherwise, all content is licensed under the Creative Commons 4 | Attribution License and code licensed under the MIT License. 5 | 6 | Copies of all licenses are included in this project's root directory. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHP Framework Interoperability Group 2 | ==================================== 3 | 4 | The idea behind the group is for project representatives to talk about the 5 | commonalities between our projects and find ways we can work together. Our main 6 | audience is each other, but we’re very aware that the rest of the PHP community 7 | is watching. If other folks want to adopt what we’re doing they are welcome to 8 | do so, but that is not the aim. 9 | 10 | Proposing a Standard Recommendation 11 | ------------------------------------ 12 | 13 | To propose a PHP Standard Recommendation (PSR): 14 | 15 | - fork this repo, create a branch, checkout that branch, add the PSR in 16 | `proposed/`, push the branch to Github, and send a pull request; or, 17 | 18 | - create a ticket to start a discussion on Github; or, 19 | 20 | - start a conversation on the [mailing list][]. 21 | 22 | [mailing list]: http://groups.google.com/group/php-fig/ 23 | 24 | GitHub usage 25 | ------------ 26 | 27 | All discussion regarding a PSR happens on the [mailing list][]. Issues filed 28 | in GitHub are rarely monitored, and PRs are likely to be missed unless a message 29 | is sent to the mailing list regarding them. Reviews of a proposed PSR should be 30 | conducted on the mailing list, not through PR comments for the same reason. 31 | 32 | Please do not simply file an issue or PR and walk-away. The most likely outcome 33 | is that it will never get seen or addressed. 34 | 35 | Requesting Membership 36 | --------------------- 37 | 38 | You **do not** need to be a voting member to participate in discussion on 39 | the [mailing list][]. 40 | 41 | To become a voting member, you must send an email to the [mailing list][]. 42 | 43 | - The subject line should read: `Membership Request: {$your_name} ({$project_name})` 44 | 45 | - The body should include your name, the name of (and link to) the project you 46 | represent, and other details you feel are relevant. 47 | 48 | - Current members will vote on your request. 49 | 50 | Do not combine separate membership requests in a single thread; one request 51 | per thread, please. 52 | 53 | Language & Translations 54 | ----------------------- 55 | 56 | All PSRs are written in British English or American English (Different specifications 57 | may vary, but it is consistent within the same specification). The PHP FIG does not 58 | offer official translations into other languages but other external entities are free 59 | to translate the specifications in accordance with the license. 60 | 61 | Voting Members 62 | -------------- 63 | 64 | The current list of voting members is available on the [project website][]. 65 | 66 | [project website]: https://www.php-fig.org/ 67 | -------------------------------------------------------------------------------- /accepted/PSR-0.md: -------------------------------------------------------------------------------- 1 | Autoloading Standard 2 | ==================== 3 | 4 | > **Deprecated** - As of 2014-10-21 PSR-0 has been marked as deprecated. [PSR-4] is now recommended 5 | as an alternative. 6 | 7 | [PSR-4]: https://www.php-fig.org/psr/psr-4/ 8 | 9 | The following describes the mandatory requirements that must be adhered 10 | to for autoloader interoperability. 11 | 12 | Mandatory 13 | --------- 14 | 15 | * A fully-qualified namespace and class must have the following 16 | structure `\\(\)*` 17 | * Each namespace must have a top-level namespace ("Vendor Name"). 18 | * Each namespace can have as many sub-namespaces as it wishes. 19 | * Each namespace separator is converted to a `DIRECTORY_SEPARATOR` when 20 | loading from the file system. 21 | * Each `_` character in the CLASS NAME is converted to a 22 | `DIRECTORY_SEPARATOR`. The `_` character has no special meaning in the 23 | namespace. 24 | * The fully-qualified namespace and class are suffixed with `.php` when 25 | loading from the file system. 26 | * Alphabetic characters in vendor names, namespaces, and class names may 27 | be of any combination of lower case and upper case. 28 | 29 | Examples 30 | -------- 31 | 32 | * `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php` 33 | * `\Symfony\Core\Request` => `/path/to/project/lib/vendor/Symfony/Core/Request.php` 34 | * `\Zend\Acl` => `/path/to/project/lib/vendor/Zend/Acl.php` 35 | * `\Zend\Mail\Message` => `/path/to/project/lib/vendor/Zend/Mail/Message.php` 36 | 37 | Underscores in Namespaces and Class Names 38 | ----------------------------------------- 39 | 40 | * `\namespace\package\Class_Name` => `/path/to/project/lib/vendor/namespace/package/Class/Name.php` 41 | * `\namespace\package_name\Class_Name` => `/path/to/project/lib/vendor/namespace/package_name/Class/Name.php` 42 | 43 | The standards we set here should be the lowest common denominator for 44 | painless autoloader interoperability. You can test that you are 45 | following these standards by utilizing this sample SplClassLoader 46 | implementation which is able to load PHP 5.3 classes. 47 | 48 | Example Implementation 49 | ---------------------- 50 | 51 | Below is an example function to simply demonstrate how the above 52 | proposed standards are autoloaded. 53 | 54 | ~~~php 55 | ` tags or the short-echo `` tags; it 38 | MUST NOT use the other tag variations. 39 | 40 | ### 2.2. Character Encoding 41 | 42 | PHP code MUST use only UTF-8 without BOM. 43 | 44 | ### 2.3. Side Effects 45 | 46 | A file SHOULD declare new symbols (classes, functions, constants, 47 | etc.) and cause no other side effects, or it SHOULD execute logic with side 48 | effects, but SHOULD NOT do both. 49 | 50 | The phrase "side effects" means execution of logic not directly related to 51 | declaring classes, functions, constants, etc., *merely from including the 52 | file*. 53 | 54 | "Side effects" include but are not limited to: generating output, explicit 55 | use of `require` or `include`, connecting to external services, modifying ini 56 | settings, emitting errors or exceptions, modifying global or static variables, 57 | reading from or writing to a file, and so on. 58 | 59 | The following is an example of a file with both declarations and side effects; 60 | i.e, an example of what to avoid: 61 | 62 | ~~~php 63 | \n"; 72 | 73 | // declaration 74 | function foo() 75 | { 76 | // function body 77 | } 78 | ~~~ 79 | 80 | The following example is of a file that contains declarations without side 81 | effects; i.e., an example of what to emulate: 82 | 83 | ~~~php 84 | 69 | ### 3.1. `Psr\Container\ContainerInterface` 70 | 71 | ~~~php 72 | 116 | ### 3.2. `Psr\Container\ContainerExceptionInterface` 117 | 118 | ~~~php 119 | 131 | ### 3.3. `Psr\Container\NotFoundExceptionInterface` 132 | 133 | ~~~php 134 | The intent of this guide is to reduce cognitive friction when scanning code from 40 | > different authors. It does so by enumerating a shared set of rules and expectations 41 | > about how to format PHP code. 42 | > When various authors collaborate across multiple projects, it helps to have one set 43 | > of guidelines to be used among all those projects. Thus, the benefit of this guide is 44 | > not in the rules themselves, but in the sharing of those rules. 45 | 46 | This PSR is an extension of PSR-2, and therefore also an extension of PSR-1. The basis of 47 | PSR-12 is PSR-2 and therefore a list of differences is provided below to assist with migration 48 | but it should be considered as an independent specification. 49 | 50 | This PSR will include coding style guidelines related to new functionality added to PHP 51 | after the publication of PSR-2; this includes PHP 5.5, PHP 5.6 and PHP 7.0. This PSR will 52 | also include clarifications on the text of PSR-2, as described in the PSR-2 Errata. 53 | 54 | ## 3.2. Non-Goals 55 | 56 | It is not the intention of this PSR to add entirely new coding style guidelines. PSR-12 will 57 | also not change anything stipulated in PSR-1 and PSR-2. 58 | 59 | # 4. Approaches 60 | 61 | The overarching approach is to attempt to apply existing PSR-2 styling and rationale to 62 | new functionality as opposed to establishing new conventions. 63 | 64 | ## 4.1. Strict Types Declarations 65 | 66 | There was a discussion about whether or not strict types should be enforced in the standard 67 | https://github.com/cs-extended/fig-standards/issues/7. All were in agreement we should only 68 | use a MUST or MUST NOT statement and avoid the use of a SHOULD statement and nobody wanted 69 | to say that strict types could not be declared. The discussion was whether it should be 70 | considered a coding style item which should be covered or whether it was out of scope and it 71 | was decided to be out of scope of a coding style guide. 72 | 73 | ## 4.2. Finally and Return Types Declaration Spacing 74 | 75 | Numerous different options were suggested and they can be seen 76 | [here for return type declarations](https://gist.github.com/michaelcullum/c025f3870c9ea1dd2668#file-returntypesspacing-php) or 77 | [here for finally blocks](https://gist.github.com/michaelcullum/c025f3870c9ea1dd2668#file-finallyblocks-php) 78 | and the current implementation was chosen due to consistency with other parts of the PSR-12 79 | specification that came from PSR-2. 80 | 81 | ## 4.3. Enforcing short form for all type keywords 82 | 83 | PHP 7.0 introduced [scalar types declaration](http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration) 84 | which does not support long type aliases. Therefore it makes sense to enforce primary short type forms to be used to 85 | have uniform syntax and prevent possible confusion. 86 | 87 | ## 4.4. Public Survey 88 | 89 | In order to settle things using data, survey was conducted and responses from 142 people 90 | including 17 project representatives were gathered: 91 | 92 | ### 4.4.1. PHP-FIG Representative Results 93 | 94 | | Representative | Project | Compound namespaces with a depth of two or more MUST not be used | Header statement grouping and ordering | Declare statements must each be on their own line | Declare statements in PHP files containing markup | Declare statements have no spaces: `declare(strict_types=1);` | Block declare statement formatting | `new` keyword usage, parenthesis required |Return type declaration formatting |Use statement leading slashes disallowed | Block namespace declaration formatting | General operator spacing |Try, Catch, Finally formatting | Anonymous class declaration formatting | Keyword casing, only lower case | Type keywords, short form only | 95 | | -------------- | ------- | ---------------------------------------------------- | ---------------------------------- | ----------------------------------------- | ------------------------------------------- | -------------------------------------------------------- | ------------------------------- | ------------------------------------- |------------------------------- |------------------------------------ | ----------------------------------- | ---------------------- |--------------------------- | ----------------------------------- | --------------------------- | -------------------------- | 96 | | Alexander Makarov | Yii framework | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 97 | | Korvin Szanto | concrete5 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 98 | | Leo Feyer | Contao | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 99 | | Larry Garfield | Drupal | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ❌ | ✓ | ✓ | 100 | | André R. | eZ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 101 | | Jan Schneider | Horde | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 102 | | Karsten Dambekalns | Neos and Flow | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 103 | | Andres Gutierrez | Phalcon | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 104 | | Ryan Thompson | PyroCMS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | 105 | | Matteo Beccati | Revive Adserver | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | 106 | | Damian Mooyman | SilverStripe | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 107 | | Brian Retterer | Stormpath PHP SDK | ✓ | ✓ | ✓ | ❌ | ❌ | ✓ | ❌ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ❌ | ❌ | 108 | | Matthew Weier O'Phinney | Zend Framework | ❌ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 109 | | Jordi Boggiano | Composer | ❌ | ❌ | ❌ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 110 | | Ben Marks | Magento | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 111 | | Chuck Burgess | PEAR | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 112 | | | **Totals**: |13/3|15/1|15/1|13/3|14/2|15/1|14/2|15/1|14/2|14/2|15/1|16/0|15/1|15/1|15/1| 113 | 114 | ### 4.4.2. General non-representative voters 115 | 116 | | Question | For | Against | Percentage For | 117 | | -------- | --- | ------- | -------------- | 118 | | Compound namespaces required depth | 114 | 12 | 89.47% | 119 | | Header statement grouping and ordering | 113 | 13 | 88.5% | 120 | | Declare statements must each be on their own line | 120 | 6 | 95% | 121 | | Declare statements in PHP files containing markup | 119 | 7 | 94.12% | 122 | | Declare statements have no spaces | 116 | 10 | 91.38% | 123 | | Block declare statement formatting | 118 | 8 | 93.22% | 124 | | `new` keyword usage, parenthesis required | 116 | 10 | 91.38% | 125 | | Return type declaration formatting | 115 | 11 | 90.43% | 126 | | Use statement leading slashes disallowed | 118 | 8 | 93.22% | 127 | | Block namespace declaration formatting | 120 | 6 | 95% | 128 | | General operator spacing | 123 | 3 | 97.56% | 129 | | Try, Catch, Finally formatting | 124 | 2 | 98.39% | 130 | | Anonymous class declaration formatting | 117 | 9 | 92.31% | 131 | | Keyword casing, only lower case | 124 | 2 | 98.39% | 132 | | Type keywords, short form only | 121 | 5 | 95.87% | 133 | 134 | ## 4.5. Multiline Function Arguments Mixed With Multiline Return 135 | 136 | A potential readability issue [was raised on the mailing list](https://groups.google.com/d/msg/php-fig/ULSL4gqK8GY/cgDELuPOCQAJ). 137 | We reviewed options for changes to the specification that could provide better readability and 138 | the floated option was to require a blank line after the opening bracket of a function if the 139 | arguments and the return are both multiline. Instead it was pointed out that this specification 140 | _already_ allows you to decide where you'd like to add blank lines and so we will leave it to 141 | the implementors to decide. 142 | 143 | # 5. Changelog from PSR-2 144 | 145 | Please note this changelog is not a verbose list of changes from PSR-2 but highlights the most 146 | notable changes. It should be considered a new specification and therefore you should read the 147 | specification for a full understanding of its contents. 148 | 149 | ## 5.1. New Statements 150 | 151 | * Lowercase for all keywords - Section 2.5 152 | * Short form for all type keywords - Section 2.5 153 | * Use statement grouping - Section 3 154 | * Use statement blocks - Section 3 155 | * Declare statement/Strict types declaration usage - Section 3 156 | * Parentheses are always required for class instantiation - Section 4 157 | * Typed properties - Section 4.3 158 | * Return type declarations - Section 4.5 159 | * Variadic and reference argument operators - Section 4.5 160 | * Type hints - Section 4.5 161 | * Add finally block - Section 5.6 162 | * Operators - Section 6 163 | * Unary operators - Section 6.1 164 | * Binary operators - Section 6.2 165 | * Ternary operators - Section 6.3 166 | * Anonymous classes - Section 8 167 | 168 | ## 5.2. Clarifications and Errata 169 | 170 | * Adjust 'methods' to 'methods and functions' in a number of instances - Throughout 171 | * Adjust references to classes and interfaces to also include traits - Throughout 172 | * StudlyCaps meaning clarified as PascalCase - Section 2.1 173 | * The last line should not be blank but contain an EOL character - Section 2.2 174 | * Blank lines may be added for readability except where explicitly forbidden within the PSR - Section 2.3 175 | * PSR-2 errata statement about multi-line arguments - Section 4 176 | * PSR-2 errata statement about extending multiple interfaces - Section 4 177 | * Forbid blank lines before/after closing/opening braces for classes - Section 4 178 | 179 | # 6. People 180 | 181 | ## 6.1. Editor: 182 | * Korvin Szanto 183 | 184 | ## 6.2. Sponsor: 185 | 186 | * Chris Tankersley 187 | 188 | ## 6.3. Working Group Members: 189 | 190 | * Alessandro Lai 191 | * Alexander Makarov 192 | * Michael Cullum 193 | * Robert Deutz 194 | 195 | ## 6.4. Special Thanks 196 | 197 | * Michael Cullum for drafting the original specification 198 | * Alexandar Makarov for coordinating the draft during PHP-FIG 2.0 199 | * Cees-Jan Kiewiet for moral support 200 | 201 | # 7. Votes 202 | 203 | * **Entrance Vote:** https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/php-fig/P9atZLOcUBM/_jwkvlYKEAAJ 204 | * **Approval Vote:** https://groups.google.com/forum/#!topic/php-fig/1uaeSMaDGbk 205 | 206 | # 8. Relevant Links 207 | 208 | _**Note:** Order descending chronologically._ 209 | 210 | * [Inspiration Mailing List Thread](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/php-fig/wh9avopSR9k) 211 | * [Initial Mailing List PSR Proposal Thread](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/php-fig/MkFacLdfGso) 212 | -------------------------------------------------------------------------------- /accepted/PSR-13-links-meta.md: -------------------------------------------------------------------------------- 1 | # Link Definition Meta Document 2 | 3 | ## 1. Summary 4 | 5 | Hypermedia links are becoming an increasingly important part of the web, in both HTML contexts 6 | and various API format contexts. However, there is no single common hypermedia format, nor 7 | is there a common way to represent Links between formats. 8 | 9 | This specification aims to provide PHP developers with a simple, common way of representing a 10 | hypermedia link independently of the serialization format that is used. That in turn allows 11 | a system to serialize a response with hypermedia links into one or more wire formats independently 12 | of the process of deciding what those links should be. 13 | 14 | ## 2. Scope 15 | 16 | ### 2.1 Goals 17 | 18 | * This specification aims to extract and standardize hypermedia link representation between different 19 | formats. 20 | 21 | ### 2.2 Non-Goals 22 | 23 | * This specification does not seek to standardize or favor any particular hypermedia serialization format. 24 | 25 | ## 3. Design Decisions 26 | 27 | ### Why no mutator methods? 28 | 29 | One of the key targets for this specification is PSR-7 Response objects. Response objects by design must be 30 | immutable. Other value-object implementations likely would also require an immutable interface. 31 | 32 | Additionally, some Link Provider objects may not be value objects but other objects within a given 33 | domain, which are able to generate Links on the fly, perhaps off of a database result or other underlying 34 | representation. In those cases a writeable provider definition would be incompatible. 35 | 36 | Therefore, this specification splits accessor methods and evolvable methods into separate interfaces, 37 | allowing objects to implement just the read-only or evolvable versions as appropriate to their use case. 38 | 39 | ### Why is rel on a Link object multi-value? 40 | 41 | Different hypermedia standards handle multiple links with the same relationship differently. Some have a single 42 | link that has multiple rel's defined. Others have a single rel entry that then contains multiple links. 43 | 44 | Defining each Link uniquely but allowing it to have multiple rels provides a most-compatible-denominator definition. 45 | A single LinkInterface object may be serialized to one or more link entries in a given hypermedia format, as 46 | appropriate. However, specifying multiple link objects each with a single rel yet the same URI is also legal, and 47 | a hypermedia format can serialize that as appropriate, too. 48 | 49 | ### Why is a LinkProviderInterface needed? 50 | 51 | In many contexts, a set of links will be attached to some other object. Those objects may be used in situations 52 | where all that is relevant is their links, or some subset of their links. For example, various different value 53 | objects may be defined that represent different REST formats such as HAL, JSON-LD, or Atom. It may be useful 54 | to extract those links from such an object uniformly for further processing. For instance, next/previous links 55 | may be extracted from an object and added to a PSR-7 Response object as Link headers. Alternatively, many links 56 | would make sense to represent with a "preload" link relationship, which would indicate to an HTTP 2-compatible 57 | web server that the linked resources should be streamed to a client in anticipation of a subsequent request. 58 | 59 | All of those cases are independent of the payload or encoding of the object. By providing a common interface 60 | to access such links, we enable generic handling of the links themselves regardless of the value object or 61 | domain object that is producing them. 62 | 63 | ## 4. People 64 | 65 | ### 4.1 Editor(s) 66 | 67 | * Larry Garfield 68 | 69 | ### 4.2 Sponsors 70 | 71 | * Matthew Weier O'Phinney (coordinator) 72 | * Marc Alexander 73 | 74 | ### 4.3 Contributors 75 | 76 | * Evert Pot 77 | 78 | ## 5. Votes 79 | 80 | ## 6. Relevant links 81 | 82 | * [What's in a link?](http://evertpot.com/whats-in-a-link/) by Evert Pot 83 | * [FIG Link Working Group List](https://groups.google.com/forum/#!forum/php-fig-link) 84 | 85 | ## 7. Errata 86 | 87 | ### 7.1 Type additions 88 | 89 | The 1.1 release of the `psr/link` package includes scalar parameter types. The 2.0 release of the package includes return types. This structure leverages PHP 7.2 covariance support to allow for a gradual upgrade process, but requires PHP 8.0 for type compatibility. 90 | 91 | Implementers MAY add return types to their own packages at their discretion, provided that: 92 | 93 | * the return types match those in the 2.0 package. 94 | * the implementation specifies a minimum PHP version of 8.0.0 or later. 95 | 96 | Implementers MAY add parameter types to their own packages in a new major release, either at the same time as adding return types or in a subsequent release, provided that: 97 | 98 | * the parameter types match those in the 1.1 package. 99 | * the implementation specifies a minimum PHP version of 8.0.0 or later. 100 | * the implementation depends on `"psr/link": "^1.1 || ^2.0"` so as to exclude the untyped 1.0 version. 101 | 102 | Implementers are encouraged but not required to transition their packages toward the 2.0 version of the package at their earliest convenience. 103 | 104 | ### 7.2 Attribute type handling 105 | 106 | The original specification contained an inconsistency regarding array values for attributes. The text of the specification states in section 1.2 that attribute values (as passed to `EvolvableLinkInterface::withAttribute()`) could be of multiple types, some of which allowed for special handling (such as booleans or arrays). However, the docblock for that method specified that the `$value` parameter had to be a string, which was incorrect. 107 | 108 | To address this issue, the interface has been corrected in later releases to allow `$value` to be of type `string|\Stringable|int|float|bool|array`. Implementers SHOULD treat a `Stringable` object the same as a `string` parameter. Implementers MAY serialize `int`, `float`, or `bool` in alternate, type-aware ways for a particular serialization format as appropriate. Other object types or resources remain disallowed. 109 | 110 | Multiple calls to `withAttribute()` with the same `$name` MUST override previously provided values, as the spec already states. To provide multiple values to a particular attribute, pass an `array` with the desired values. 111 | 112 | All other guidelines and requirements in section 1.2 remain valid. 113 | -------------------------------------------------------------------------------- /accepted/PSR-14-event-dispatcher.md: -------------------------------------------------------------------------------- 1 | Event Dispatcher 2 | ================ 3 | 4 | Event Dispatching is a common and well-tested mechanism to allow developers to inject logic into an application easily and consistently. 5 | 6 | The goal of this PSR is to establish a common mechanism for event-based extension and collaboration so that libraries and components may be reused more freely between various applications and frameworks. 7 | 8 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119][]. 9 | 10 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 11 | 12 | ## Goal 13 | 14 | Having common interfaces for dispatching and handling events allows developers to create libraries that can interact with many frameworks and other libraries in a common fashion. 15 | 16 | Some examples: 17 | 18 | * A security framework that will prevent saving/accessing data when a user doesn't have permission. 19 | * A common full page caching system. 20 | * Libraries that extend other libraries, regardless of what framework they are both integrated into. 21 | * A logging package to track all actions taken within the application 22 | 23 | ## Definitions 24 | 25 | * **Event** - An Event is a message produced by an *Emitter*. It may be any arbitrary PHP object. 26 | * **Listener** - A Listener is any PHP callable that expects to be passed an Event. Zero or more Listeners may be passed the same Event. A Listener MAY enqueue some other asynchronous behavior if it so chooses. 27 | * **Emitter** - An Emitter is any arbitrary code that wishes to dispatch an Event. This is also known as the "calling code". It is not represented by any particular data structure but refers to the use case. 28 | * **Dispatcher** - A Dispatcher is a service object that is given an Event object by an Emitter. The Dispatcher is responsible for ensuring that the Event is passed to all relevant Listeners, but MUST defer determining the responsible listeners to a Listener Provider. 29 | * **Listener Provider** - A Listener Provider is responsible for determining what Listeners are relevant for a given Event, but MUST NOT call the Listeners itself. A Listener Provider may specify zero or more relevant Listeners. 30 | 31 | ## Events 32 | 33 | Events are objects that act as the unit of communication between an Emitter and appropriate Listeners. 34 | 35 | Event objects MAY be mutable should the use case call for Listeners providing information back to the Emitter. However, if no such bidirectional communication is needed then it is RECOMMENDED that the Event be defined as immutable; i.e., defined such that it lacks mutator methods. 36 | 37 | Implementers MUST assume that the same object will be passed to all Listeners. 38 | 39 | It is RECOMMENDED, but NOT REQUIRED, that Event objects support lossless serialization and deserialization; `$event == unserialize(serialize($event))` SHOULD hold true. Objects MAY leverage PHP’s `Serializable` interface, `__sleep()` or `__wakeup()` magic methods, or similar language functionality if appropriate. 40 | 41 | ## Stoppable Events 42 | 43 | A **Stoppable Event** is a special case of Event that contains additional ways to prevent further Listeners from being called. It is indicated by implementing the `StoppableEventInterface`. 44 | 45 | An Event that implements `StoppableEventInterface` MUST return `true` from `isPropagationStopped()` when whatever Event it represents has been completed. It is up to the implementer of the class to determine when that is. For example, an Event that is asking for a PSR-7 `RequestInterface` object to be matched with a corresponding `ResponseInterface` object could have a `setResponse(ResponseInterface $res)` method for a Listener to call, which causes `isPropagationStopped()` to return `true`. 46 | 47 | ## Listeners 48 | 49 | A Listener may be any PHP callable. A Listener MUST have one and only one parameter, which is the Event to which it responds. Listeners SHOULD type hint that parameter as specifically as is relevant for their use case; that is, a Listener MAY type hint against an interface to indicate it is compatible with any Event type that implements that interface, or to a specific implementation of that interface. 50 | 51 | A Listener SHOULD have a `void` return, and SHOULD type hint that return explicitly. A Dispatcher MUST ignore return values from Listeners. 52 | 53 | A Listener MAY delegate actions to other code. That includes a Listener being a thin wrapper around an object that runs the actual business logic. 54 | 55 | A Listener MAY enqueue information from the Event for later processing by a secondary process, using cron, a queue server, or similar techniques. It MAY serialize the Event object itself to do so; however, care should be taken that not all Event objects may be safely serializable. A secondary process MUST assume that any changes it makes to an Event object will NOT propagate to other Listeners. 56 | 57 | ## Dispatcher 58 | 59 | A Dispatcher is a service object implementing `EventDispatcherInterface`. It is responsible for retrieving Listeners from a Listener Provider for the Event dispatched, and invoking each Listener with that Event. 60 | 61 | A Dispatcher: 62 | 63 | * MUST call Listeners synchronously in the order they are returned from a ListenerProvider. 64 | * MUST return the same Event object it was passed after it is done invoking Listeners. 65 | * MUST NOT return to the Emitter until all Listeners have executed. 66 | 67 | If passed a Stoppable Event, a Dispatcher 68 | 69 | * MUST call `isPropagationStopped()` on the Event before each Listener has been called. If that method returns `true` it MUST return the Event to the Emitter immediately and MUST NOT call any further Listeners. This implies that if an Event is passed to the Dispatcher that always returns `true` from `isPropagationStopped()`, zero listeners will be called. 70 | 71 | A Dispatcher SHOULD assume that any Listener returned to it from a Listener Provider is type-safe. That is, the Dispatcher SHOULD assume that calling `$listener($event)` will not produce a `TypeError`. 72 | 73 | [Promise object]: https://promisesaplus.com/ 74 | 75 | ### Error handling 76 | 77 | An Exception or Error thrown by a Listener MUST block the execution of any further Listeners. An Exception or Error thrown by a Listener MUST be allowed to propagate back up to the Emitter. 78 | 79 | A Dispatcher MAY catch a thrown object to log it, allow additional action to be taken, etc., but then MUST rethrow the original throwable. 80 | 81 | ## Listener Provider 82 | 83 | A Listener Provider is a service object responsible for determining what Listeners are relevant to and should be called for a given Event. It may determine both what Listeners are relevant and the order in which to return them by whatever means it chooses. That MAY include: 84 | 85 | * Allowing for some form of registration mechanism so that implementers may assign a Listener to an Event in a fixed order. 86 | * Deriving a list of applicable Listeners through reflection based on the type and implemented interfaces of the Event. 87 | * Generating a compiled list of Listeners ahead of time that may be consulted at runtime. 88 | * Implementing some form of access control so that certain Listeners will only be called if the current user has a certain permission. 89 | * Extracting some information from an object referenced by the Event, such as an Entity, and calling pre-defined lifecycle methods on that object. 90 | * Delegating its responsibility to one or more other Listener Providers using some arbitrary logic. 91 | 92 | Any combination of the above, or other mechanisms, MAY be used as desired. 93 | 94 | Listener Providers SHOULD use the class name of an Event to differentiate one event from another. They MAY also consider any other information on the event as appropriate. 95 | 96 | Listener Providers MUST treat parent types identically to the Event's own type when determining listener applicability. In the following case: 97 | 98 | ```php 99 | class A {} 100 | 101 | class B extends A {} 102 | 103 | $b = new B(); 104 | 105 | function listener(A $event): void {}; 106 | ``` 107 | 108 | A Listener Provider MUST treat `listener()` as an applicable listener for `$b`, as it is type compatible, unless some other criteria prevents it from doing so. 109 | 110 | ## Object composition 111 | 112 | A Dispatcher SHOULD compose a Listener Provider to determine relevant listeners. It is RECOMMENDED that a Listener Provider be implemented as a distinct object from the Dispatcher but that is NOT REQUIRED. 113 | 114 | ## Interfaces 115 | 116 | ```php 117 | namespace Psr\EventDispatcher; 118 | 119 | /** 120 | * Defines a dispatcher for events. 121 | */ 122 | interface EventDispatcherInterface 123 | { 124 | /** 125 | * Provide all relevant listeners with an event to process. 126 | * 127 | * @param object $event 128 | * The object to process. 129 | * 130 | * @return object 131 | * The Event that was passed, now modified by listeners. 132 | */ 133 | public function dispatch(object $event); 134 | } 135 | ``` 136 | 137 | ```php 138 | namespace Psr\EventDispatcher; 139 | 140 | /** 141 | * Mapper from an event to the listeners that are applicable to that event. 142 | */ 143 | interface ListenerProviderInterface 144 | { 145 | /** 146 | * @param object $event 147 | * An event for which to return the relevant listeners. 148 | * @return iterable 149 | * An iterable (array, iterator, or generator) of callables. Each 150 | * callable MUST be type-compatible with $event. 151 | */ 152 | public function getListenersForEvent(object $event) : iterable; 153 | } 154 | ``` 155 | 156 | ```php 157 | namespace Psr\EventDispatcher; 158 | 159 | /** 160 | * An Event whose processing may be interrupted when the event has been handled. 161 | * 162 | * A Dispatcher implementation MUST check to determine if an Event 163 | * is marked as stopped after each listener is called. If it is then it should 164 | * return immediately without calling any further Listeners. 165 | */ 166 | interface StoppableEventInterface 167 | { 168 | /** 169 | * Is propagation stopped? 170 | * 171 | * This will typically only be used by the Dispatcher to determine if the 172 | * previous listener halted propagation. 173 | * 174 | * @return bool 175 | * True if the Event is complete and no further listeners should be called. 176 | * False to continue calling listeners. 177 | */ 178 | public function isPropagationStopped() : bool; 179 | } 180 | ``` 181 | -------------------------------------------------------------------------------- /accepted/PSR-15-request-handlers.md: -------------------------------------------------------------------------------- 1 | HTTP Server Request Handlers 2 | ============================ 3 | 4 | This document describes common interfaces for HTTP server request handlers 5 | ("request handlers") and HTTP server middleware components ("middleware") 6 | that use HTTP messages as described by [PSR-7][psr7] or subsequent 7 | replacement PSRs. 8 | 9 | HTTP request handlers are a fundamental part of any web application. Server-side 10 | code receives a request message, processes it, and produces a response message. 11 | HTTP middleware is a way to move common request and response processing away from 12 | the application layer. 13 | 14 | The interfaces described in this document are abstractions for request handlers 15 | and middleware. 16 | 17 | _Note: All references to "request handlers" and "middleware" are specific to 18 | **server request** processing._ 19 | 20 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 21 | "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 22 | interpreted as described in [RFC 2119][rfc2119]. 23 | 24 | [psr7]: https://www.php-fig.org/psr/psr-7/ 25 | [rfc2119]: http://tools.ietf.org/html/rfc2119 26 | 27 | ### References 28 | 29 | - [PSR-7][psr7] 30 | - [RFC 2119][rfc2119] 31 | 32 | ## 1. Specification 33 | 34 | ### 1.1 Request Handlers 35 | 36 | A request handler is an individual component that processes a request and 37 | produces a response, as defined by PSR-7. 38 | 39 | A request handler MAY throw an exception if request conditions prevent it from 40 | producing a response. The type of exception is not defined. 41 | 42 | Request handlers using this standard MUST implement the following interface: 43 | 44 | - `Psr\Http\Server\RequestHandlerInterface` 45 | 46 | ### 1.2 Middleware 47 | 48 | A middleware component is an individual component participating, often together 49 | with other middleware components, in the processing of an incoming request and 50 | the creation of a resulting response, as defined by PSR-7. 51 | 52 | A middleware component MAY create and return a response without delegating to 53 | a request handler, if sufficient conditions are met. 54 | 55 | Middleware using this standard MUST implement the following interface: 56 | 57 | - `Psr\Http\Server\MiddlewareInterface` 58 | 59 | ### 1.3 Generating Responses 60 | 61 | It is RECOMMENDED that any middleware or request handler that generates a response 62 | will either compose a prototype of a PSR-7 `ResponseInterface` or a factory capable 63 | of generating a `ResponseInterface` instance in order to prevent dependence on a 64 | specific HTTP message implementation. 65 | 66 | ### 1.4 Handling Exceptions 67 | 68 | It is RECOMMENDED that any application using middleware includes a component 69 | that catches exceptions and converts them into responses. This middleware SHOULD 70 | be the first component executed and wrap all further processing to ensure that 71 | a response is always generated. 72 | 73 | ## 2. Interfaces 74 | 75 | ### 2.1 Psr\Http\Server\RequestHandlerInterface 76 | 77 | The following interface MUST be implemented by request handlers. 78 | 79 | ```php 80 | namespace Psr\Http\Server; 81 | 82 | use Psr\Http\Message\ResponseInterface; 83 | use Psr\Http\Message\ServerRequestInterface; 84 | 85 | /** 86 | * Handles a server request and produces a response. 87 | * 88 | * An HTTP request handler process an HTTP request in order to produce an 89 | * HTTP response. 90 | */ 91 | interface RequestHandlerInterface 92 | { 93 | /** 94 | * Handles a request and produces a response. 95 | * 96 | * May call other collaborating code to generate the response. 97 | */ 98 | public function handle(ServerRequestInterface $request): ResponseInterface; 99 | } 100 | ``` 101 | 102 | ### 2.2 Psr\Http\Server\MiddlewareInterface 103 | 104 | The following interface MUST be implemented by compatible middleware components. 105 | 106 | ```php 107 | namespace Psr\Http\Server; 108 | 109 | use Psr\Http\Message\ResponseInterface; 110 | use Psr\Http\Message\ServerRequestInterface; 111 | 112 | /** 113 | * Participant in processing a server request and response. 114 | * 115 | * An HTTP middleware component participates in processing an HTTP message: 116 | * by acting on the request, generating the response, or forwarding the 117 | * request to a subsequent middleware and possibly acting on its response. 118 | */ 119 | interface MiddlewareInterface 120 | { 121 | /** 122 | * Process an incoming server request. 123 | * 124 | * Processes an incoming server request in order to produce a response. 125 | * If unable to produce the response itself, it may delegate to the provided 126 | * request handler to do so. 127 | */ 128 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface; 129 | } 130 | ``` 131 | -------------------------------------------------------------------------------- /accepted/PSR-16-simple-cache-meta.md: -------------------------------------------------------------------------------- 1 | # PSR-16 Meta Document 2 | 3 | ## 1. Summary 4 | 5 | Caching is a common way to improve the performance of any project, and many 6 | libraries make use or could make use of it. Interoperability at this level 7 | means libraries can drop their own caching implementations and easily rely 8 | on the one given to them by the framework, or another dedicated cache 9 | library the user picked. 10 | 11 | ## 2. Why Bother? 12 | 13 | PSR-6 solves this problem already, but in a rather formal and verbose way for 14 | what the most simple use cases need. This simpler approach aims to build a 15 | standardized layer of simplicity on top of the existing PSR-6 interfaces. 16 | 17 | ## 3. Scope 18 | 19 | ### 3.1 Goals 20 | 21 | * A simple interface for cache operations. 22 | * Basic support for operations on multiple keys for performance (round-trip-time) 23 | reasons. 24 | * Providing an adapter class that turns a PSR-6 implementation into a 25 | PSR-Simple-Cache one. 26 | * It should be possible to expose both caching PSRs from a caching library. 27 | 28 | ### 3.2 Non-Goals 29 | 30 | * Solving all possible edge cases, PSR-6 does this well already. 31 | 32 | ## 4. Approaches 33 | 34 | The approach chosen here is very barebones by design, as it is to be used 35 | only by the most simple cases. It does not have to be implementable by all 36 | possible cache backends, nor be usable for all usages. It is merely a layer 37 | of convenience on top of PSR-6. 38 | 39 | ## 5. People 40 | 41 | ### 5.1 Editor(s) 42 | 43 | * Paul Dragoonis (@dragoonis) 44 | 45 | ### 5.2 Sponsors 46 | 47 | * Jordi Boggiano (@seldaek) - Composer (Coordinator) 48 | * Fabien Potencier (@fabpot) - Symfony 49 | 50 | ### 5.3 Contributors 51 | 52 | For their role in the writing the initial version of this cache PSR: 53 | 54 | * Evert Pot (@evert) 55 | * Florin Pățan (@dlsniper) 56 | 57 | For being an early reviewer 58 | 59 | * Daniel Messenger (@dannym87) 60 | 61 | ## 6. Votes 62 | 63 | * **Entrance Vote:** https://groups.google.com/d/topic/php-fig/vyQTKHS6pJ8/discussion 64 | * **Acceptance Vote:** https://groups.google.com/d/msg/php-fig/A8e6GvDRGIk/HQBJGEhbDQAJ 65 | 66 | ## 7. Relevant Links 67 | 68 | * [Survey of existing cache implementations][1], by @dragoonis 69 | 70 | [1]: https://docs.google.com/spreadsheet/ccc?key=0Ak2JdGialLildEM2UjlOdnA4ekg3R1Bfeng5eGlZc1E#gid=0 71 | -------------------------------------------------------------------------------- /accepted/PSR-16-simple-cache.md: -------------------------------------------------------------------------------- 1 | Common Interface for Caching Libraries 2 | ====================================== 3 | 4 | This document describes a simple yet extensible interface for a cache item and 5 | a cache driver. 6 | 7 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 8 | "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 9 | interpreted as described in [RFC 2119][]. 10 | 11 | The final implementations MAY decorate the objects with more 12 | functionality than the one proposed but they MUST implement the indicated 13 | interfaces/functionality first. 14 | 15 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 16 | 17 | # 1. Specification 18 | 19 | ## 1.1 Introduction 20 | 21 | Caching is a common way to improve the performance of any project, making 22 | caching libraries one of the most common features of many frameworks and 23 | libraries. Interoperability at this level means libraries can drop their 24 | own caching implementations and easily rely on the one given to them by the 25 | framework, or another dedicated cache library. 26 | 27 | PSR-6 solves this problem already, but in a rather formal and verbose way for 28 | what the most simple use cases need. This simpler approach aims to build a 29 | standardized streamlined interface for common cases. It is independent of 30 | PSR-6 but has been designed to make compatibility with PSR-6 as straightforward 31 | as possible. 32 | 33 | ## 1.2 Definitions 34 | 35 | Definitions for Calling Library, Implementing Library, TTL, Expiration and Key 36 | are copied from PSR-6 as the same assumptions are true. 37 | 38 | * **Calling Library** - The library or code that actually needs the cache 39 | services. This library will utilize caching services that implement this 40 | standard's interfaces, but will otherwise have no knowledge of the 41 | implementation of those caching services. 42 | 43 | * **Implementing Library** - This library is responsible for implementing 44 | this standard in order to provide caching services to any Calling Library. The 45 | Implementing Library MUST provide a class implementing the Psr\SimpleCache\CacheInterface interface. 46 | Implementing Libraries MUST support at minimum TTL functionality as described 47 | below with whole-second granularity. 48 | 49 | * **TTL** - The Time To Live (TTL) of an item is the amount of time between 50 | when that item is stored and it is considered stale. The TTL is normally defined 51 | by an integer representing time in seconds, or a DateInterval object. 52 | 53 | * **Expiration** - The actual time when an item is set to go stale. This is 54 | calculated by adding the TTL to the time when an object is stored. 55 | 56 | An item with a 300 second TTL stored at 1:30:00 will have an expiration of 1:35:00. 57 | 58 | Implementing Libraries MAY expire an item before its requested Expiration Time, 59 | but MUST treat an item as expired once its Expiration Time is reached. If a calling 60 | library asks for an item to be saved but does not specify an expiration time, or 61 | specifies a null expiration time or TTL, an Implementing Library MAY use a configured 62 | default duration. If no default duration has been set, the Implementing Library 63 | MUST interpret that as a request to cache the item forever, or for as long as the 64 | underlying implementation supports. 65 | 66 | If a negative or zero TTL is provided, the item MUST be deleted from the cache 67 | if it exists, as it is expired already. 68 | 69 | * **Key** - A string of at least one character that uniquely identifies a 70 | cached item. Implementing libraries MUST support keys consisting of the 71 | characters `A-Z`, `a-z`, `0-9`, `_`, and `.` in any order in UTF-8 encoding and a 72 | length of up to 64 characters. Implementing libraries MAY support additional 73 | characters and encodings or longer lengths, but MUST support at least that 74 | minimum. Libraries are responsible for their own escaping of key strings 75 | as appropriate, but MUST be able to return the original unmodified key string. 76 | The following characters are reserved for future extensions and MUST NOT be 77 | supported by implementing libraries: `{}()/\@:` 78 | 79 | * **Cache** - An object that implements the `Psr\SimpleCache\CacheInterface` interface. 80 | 81 | * **Cache Misses** - A cache miss will return null and therefore detecting 82 | if one stored `null` is not possible. This is the main deviation from PSR-6's 83 | assumptions. 84 | 85 | ## 1.3 Cache 86 | 87 | Implementations MAY provide a mechanism for a user to specify a default TTL 88 | if one is not specified for a specific cache item. If no user-specified default 89 | is provided implementations MUST default to the maximum legal value allowed by 90 | the underlying implementation. If the underlying implementation does not 91 | support TTL, the user-specified TTL MUST be silently ignored. 92 | 93 | ## 1.4 Data 94 | 95 | Implementing libraries MUST support all serializable PHP data types, including: 96 | 97 | * **Strings** - Character strings of arbitrary size in any PHP-compatible encoding. 98 | * **Integers** - All integers of any size supported by PHP, up to 64-bit signed. 99 | * **Floats** - All signed floating point values. 100 | * **Booleans** - True and False. 101 | * **Null** - The null value (although it will not be distinguishable from a 102 | cache miss when reading it back out). 103 | * **Arrays** - Indexed, associative and multidimensional arrays of arbitrary depth. 104 | * **Objects** - Any object that supports lossless serialization and 105 | deserialization such that $o == unserialize(serialize($o)). Objects MAY 106 | leverage PHP's Serializable interface, `__sleep()` or `__wakeup()` magic methods, 107 | or similar language functionality if appropriate. 108 | 109 | All data passed into the Implementing Library MUST be returned exactly as 110 | passed. That includes the variable type. That is, it is an error to return 111 | (string) 5 if (int) 5 was the value saved. Implementing Libraries MAY use PHP's 112 | serialize()/unserialize() functions internally but are not required to do so. 113 | Compatibility with them is simply used as a baseline for acceptable object values. 114 | 115 | If it is not possible to return the exact saved value for any reason, implementing 116 | libraries MUST respond with a cache miss rather than corrupted data. 117 | 118 | # 2. Interfaces 119 | 120 | ## 2.1 CacheInterface 121 | 122 | The cache interface defines the most basic operations on a collection of cache-entries, which 123 | entails basic reading, writing and deleting individual cache items. 124 | 125 | In addition, it has methods for dealing with multiple sets of cache entries such as writing, reading or 126 | deleting multiple cache entries at a time. This is useful when you have lots of cache reads/writes 127 | to perform, and lets you perform your operations in a single call to the cache server cutting down latency 128 | times dramatically. 129 | 130 | An instance of CacheInterface corresponds to a single collection of cache items with a single key namespace, 131 | and is equivalent to a "Pool" in PSR-6. Different CacheInterface instances MAY be backed by the same 132 | datastore, but MUST be logically independent. 133 | 134 | ~~~php 135 | value pairs. Cache keys that do not exist or are stale will have $default as value. 196 | * 197 | * @throws \Psr\SimpleCache\InvalidArgumentException 198 | * MUST be thrown if $keys is neither an array nor a Traversable, 199 | * or if any of the $keys are not a legal value. 200 | */ 201 | public function getMultiple($keys, $default = null); 202 | 203 | /** 204 | * Persists a set of key => value pairs in the cache, with an optional TTL. 205 | * 206 | * @param iterable $values A list of key => value pairs for a multiple-set operation. 207 | * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and 208 | * the driver supports TTL then the library may set a default value 209 | * for it or let the driver take care of that. 210 | * 211 | * @return bool True on success and false on failure. 212 | * 213 | * @throws \Psr\SimpleCache\InvalidArgumentException 214 | * MUST be thrown if $values is neither an array nor a Traversable, 215 | * or if any of the $values are not a legal value. 216 | */ 217 | public function setMultiple($values, $ttl = null); 218 | 219 | /** 220 | * Deletes multiple cache items in a single operation. 221 | * 222 | * @param iterable $keys A list of string-based keys to be deleted. 223 | * 224 | * @return bool True if the items were successfully removed. False if there was an error. 225 | * 226 | * @throws \Psr\SimpleCache\InvalidArgumentException 227 | * MUST be thrown if $keys is neither an array nor a Traversable, 228 | * or if any of the $keys are not a legal value. 229 | */ 230 | public function deleteMultiple($keys); 231 | 232 | /** 233 | * Determines whether an item is present in the cache. 234 | * 235 | * NOTE: It is recommended that has() is only to be used for cache warming type purposes 236 | * and not to be used within your live applications operations for get/set, as this method 237 | * is subject to a race condition where your has() will return true and immediately after, 238 | * another script can remove it, making the state of your app out of date. 239 | * 240 | * @param string $key The cache item key. 241 | * 242 | * @return bool 243 | * 244 | * @throws \Psr\SimpleCache\InvalidArgumentException 245 | * MUST be thrown if the $key string is not a legal value. 246 | */ 247 | public function has($key); 248 | } 249 | ~~~ 250 | 251 | ## 2.2 CacheException 252 | 253 | ~~~php 254 | 255 | get('/hello/{name}', function ($name) use ($app) { 33 | return 'Hello '.$app->escape($name); 34 | }); 35 | ~~~ 36 | 37 | ### 3.2 - Extending Multiple Interfaces (10/17/2013) 38 | 39 | When extending multiple interfaces, the list of `extends` should be treated the same as a list 40 | of `implements`, as declared in Section 4.1. 41 | -------------------------------------------------------------------------------- /accepted/PSR-3-logger-interface-meta.md: -------------------------------------------------------------------------------- 1 | # Logger Meta Document 2 | 3 | ## 1. Summary 4 | 5 | The logger interface defines a common interface for logging system messages from an application or library. 6 | 7 | This metadocument was written post-hoc, as PSR-3 was originally passed before meta-documents were standard practice. 8 | 9 | ## 2. Design Decisions 10 | 11 | ### Static log messages 12 | 13 | It is the intent of this specification that the message passed to a logging method always be a static value. Any context-specific variability (such as a username, timestamp, or other information) should be provided via the `$context` array only, and the string should use a placeholder to reference it. 14 | 15 | The intent of this design is twofold. One, the message is then readily available to translation systems to create localized versions of log messages. Two, context-specific data may contain user input, and thus requires escaping. That escaping will be necessarily different if the log message is stored in a database for later rendering in HTML, serialized to JSON, serialized to a syslog message string, etc. It is the responsibility of the logging implementation to ensure that `$context` data that is shown to the user is appropriately escaped. 16 | 17 | ## 3. People 18 | 19 | ### 3.1 Editor(s) 20 | 21 | * Jordi Boggiano 22 | 23 | ## 4. Votes 24 | 25 | [Approval vote](https://groups.google.com/g/php-fig/c/d0yPC7jWPAE/m/rhexAfz2T_8J) 26 | 27 | ## 5. Errata 28 | 29 | ### 5.1 Type additions 30 | 31 | The 2.0 release of the `psr/log` package includes scalar parameter types. The 3.0 release of the package includes return types. This structure leverages PHP 7.2 covariance support to allow for a gradual upgrade process, but requires PHP 8.0 for type compatibility. 32 | 33 | Implementers MAY add return types to their own packages at their discretion, provided that: 34 | 35 | * the return types match those in the 3.0 package. 36 | * the implementation specifies a minimum PHP version of 8.0.0 or later. 37 | 38 | Implementers MAY add parameter types to their own packages in a new major release, either at the same time as adding return types or in a subsequent release, provided that: 39 | 40 | * the parameter types match those in the 2.0 package. 41 | * the implementation specifies a minimum PHP version of 8.0.0 or later. 42 | * the implementation depends on `"psr/log": "^2.0 || ^3.0"` so as to exclude the untyped 1.0 version. 43 | 44 | Implementers are encouraged but not required to transition their packages toward the 3.0 version of the package at their earliest convenience. 45 | -------------------------------------------------------------------------------- /accepted/PSR-3-logger-interface.md: -------------------------------------------------------------------------------- 1 | Logger Interface 2 | ================ 3 | 4 | This document describes a common interface for logging libraries. 5 | 6 | The main goal is to allow libraries to receive a `Psr\Log\LoggerInterface` 7 | object and write logs to it in a simple and universal way. Frameworks 8 | and CMSs that have custom needs MAY extend the interface for their own 9 | purpose, but SHOULD remain compatible with this document. This ensures 10 | that the third-party libraries an application uses can write to the 11 | centralized application logs. 12 | 13 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 14 | "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 15 | interpreted as described in [RFC 2119][]. 16 | 17 | The word `implementor` in this document is to be interpreted as someone 18 | implementing the `LoggerInterface` in a log-related library or framework. 19 | Users of loggers are referred to as `user`. 20 | 21 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 22 | 23 | ## 1. Specification 24 | 25 | ### 1.1 Basics 26 | 27 | - The `LoggerInterface` exposes eight methods to write logs to the eight 28 | [RFC 5424][] levels (debug, info, notice, warning, error, critical, alert, 29 | emergency). 30 | 31 | - A ninth method, `log`, accepts a log level as the first argument. Calling this 32 | method with one of the log level constants MUST have the same result as 33 | calling the level-specific method. Calling this method with a level not 34 | defined by this specification MUST throw a `Psr\Log\InvalidArgumentException` 35 | if the implementation does not know about the level. Users SHOULD NOT use a 36 | custom level without knowing for sure the current implementation supports it. 37 | 38 | [RFC 5424]: http://tools.ietf.org/html/rfc5424 39 | 40 | ### 1.2 Message 41 | 42 | - Every method accepts a string as the message, or an object with a 43 | `__toString()` method. Implementors MAY have special handling for the passed 44 | objects. If that is not the case, implementors MUST cast it to a string. 45 | 46 | - The message MAY contain placeholders which implementors MAY replace with 47 | values from the context array. 48 | 49 | Placeholder names MUST correspond to keys in the context array. 50 | 51 | Placeholder names MUST be delimited with a single opening brace `{` and 52 | a single closing brace `}`. There MUST NOT be any whitespace between the 53 | delimiters and the placeholder name. 54 | 55 | Placeholder names SHOULD be composed only of the characters `A-Z`, `a-z`, 56 | `0-9`, underscore `_`, and period `.`. The use of other characters is 57 | reserved for future modifications of the placeholders specification. 58 | 59 | Implementors MAY use placeholders to implement various escaping strategies 60 | and translate logs for display. Users SHOULD NOT pre-escape placeholder 61 | values since they can not know in which context the data will be displayed. 62 | 63 | The following is an example implementation of placeholder interpolation 64 | provided for reference purposes only: 65 | 66 | ~~~php 67 | $val) { 77 | // check that the value can be cast to string 78 | if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { 79 | $replace['{' . $key . '}'] = $val; 80 | } 81 | } 82 | 83 | // interpolate replacement values into the message and return 84 | return strtr($message, $replace); 85 | } 86 | 87 | // a message with brace-delimited placeholder names 88 | $message = "User {username} created"; 89 | 90 | // a context array of placeholder names => replacement values 91 | $context = array('username' => 'bolivar'); 92 | 93 | // echoes "User bolivar created" 94 | echo interpolate($message, $context); 95 | ~~~ 96 | 97 | ### 1.3 Context 98 | 99 | - Every method accepts an array as context data. This is meant to hold any 100 | extraneous information that does not fit well in a string. The array can 101 | contain anything. Implementors MUST ensure they treat context data with 102 | as much lenience as possible. A given value in the context MUST NOT throw 103 | an exception nor raise any php error, warning or notice. 104 | 105 | - If an `Exception` object is passed in the context data, it MUST be in the 106 | `'exception'` key. Logging exceptions is a common pattern and this allows 107 | implementors to extract a stack trace from the exception when the log 108 | backend supports it. Implementors MUST still verify that the `'exception'` 109 | key is actually an `Exception` before using it as such, as it MAY contain 110 | anything. 111 | 112 | ### 1.4 Helper classes and interfaces 113 | 114 | - The `Psr\Log\AbstractLogger` class lets you implement the `LoggerInterface` 115 | very easily by extending it and implementing the generic `log` method. 116 | The other eight methods are forwarding the message and context to it. 117 | 118 | - Similarly, using the `Psr\Log\LoggerTrait` only requires you to 119 | implement the generic `log` method. Note that since traits can not implement 120 | interfaces, in this case you still have to implement `LoggerInterface`. 121 | 122 | - The `Psr\Log\NullLogger` is provided together with the interface. It MAY be 123 | used by users of the interface to provide a fall-back "black hole" 124 | implementation if no logger is given to them. However, conditional logging 125 | may be a better approach if context data creation is expensive. 126 | 127 | - The `Psr\Log\LoggerAwareInterface` only contains a 128 | `setLogger(LoggerInterface $logger)` method and can be used by frameworks to 129 | auto-wire arbitrary instances with a logger. 130 | 131 | - The `Psr\Log\LoggerAwareTrait` trait can be used to implement the equivalent 132 | interface easily in any class. It gives you access to `$this->logger`. 133 | 134 | - The `Psr\Log\LogLevel` class holds constants for the eight log levels. 135 | 136 | ## 2. Package 137 | 138 | The interfaces and classes described as well as relevant exception classes 139 | and a test suite to verify your implementation are provided as part of the 140 | [psr/log](https://packagist.org/packages/psr/log) package. 141 | 142 | ## 3. `Psr\Log\LoggerInterface` 143 | 144 | ~~~php 145 | register(); 90 | * 91 | * // register the base directories for the namespace prefix 92 | * $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src'); 93 | * $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests'); 94 | * 95 | * The following line would cause the autoloader to attempt to load the 96 | * \Foo\Bar\Qux\Quux class from /path/to/packages/foo-bar/src/Qux/Quux.php: 97 | * 98 | * prefixes[$prefix]) === false) { 148 | $this->prefixes[$prefix] = array(); 149 | } 150 | 151 | // retain the base directory for the namespace prefix 152 | if ($prepend) { 153 | array_unshift($this->prefixes[$prefix], $base_dir); 154 | } else { 155 | array_push($this->prefixes[$prefix], $base_dir); 156 | } 157 | } 158 | 159 | /** 160 | * Loads the class file for a given class name. 161 | * 162 | * @param string $class The fully-qualified class name. 163 | * @return mixed The mapped file name on success, or boolean false on 164 | * failure. 165 | */ 166 | public function loadClass($class) 167 | { 168 | // the current namespace prefix 169 | $prefix = $class; 170 | 171 | // work backwards through the namespace names of the fully-qualified 172 | // class name to find a mapped file name 173 | while (false !== $pos = strrpos($prefix, '\\')) { 174 | 175 | // retain the trailing namespace separator in the prefix 176 | $prefix = substr($class, 0, $pos + 1); 177 | 178 | // the rest is the relative class name 179 | $relative_class = substr($class, $pos + 1); 180 | 181 | // try to load a mapped file for the prefix and relative class 182 | $mapped_file = $this->loadMappedFile($prefix, $relative_class); 183 | if ($mapped_file) { 184 | return $mapped_file; 185 | } 186 | 187 | // remove the trailing namespace separator for the next iteration 188 | // of strrpos() 189 | $prefix = rtrim($prefix, '\\'); 190 | } 191 | 192 | // never found a mapped file 193 | return false; 194 | } 195 | 196 | /** 197 | * Load the mapped file for a namespace prefix and relative class. 198 | * 199 | * @param string $prefix The namespace prefix. 200 | * @param string $relative_class The relative class name. 201 | * @return mixed Boolean false if no mapped file can be loaded, or the 202 | * name of the mapped file that was loaded. 203 | */ 204 | protected function loadMappedFile($prefix, $relative_class) 205 | { 206 | // are there any base directories for this namespace prefix? 207 | if (isset($this->prefixes[$prefix]) === false) { 208 | return false; 209 | } 210 | 211 | // look through base directories for this namespace prefix 212 | foreach ($this->prefixes[$prefix] as $base_dir) { 213 | 214 | // replace the namespace prefix with the base directory, 215 | // replace namespace separators with directory separators 216 | // in the relative class name, append with .php 217 | $file = $base_dir 218 | . str_replace('\\', '/', $relative_class) 219 | . '.php'; 220 | 221 | // if the mapped file exists, require it 222 | if ($this->requireFile($file)) { 223 | // yes, we're done 224 | return $file; 225 | } 226 | } 227 | 228 | // never found it 229 | return false; 230 | } 231 | 232 | /** 233 | * If a file exists, require it from the file system. 234 | * 235 | * @param string $file The file to require. 236 | * @return bool True if the file exists, false if not. 237 | */ 238 | protected function requireFile($file) 239 | { 240 | if (file_exists($file)) { 241 | require $file; 242 | return true; 243 | } 244 | return false; 245 | } 246 | } 247 | ~~~ 248 | 249 | ### Unit Tests 250 | 251 | The following example is one way of unit testing the above class loader: 252 | 253 | ~~~php 254 | files = $files; 264 | } 265 | 266 | protected function requireFile($file) 267 | { 268 | return in_array($file, $this->files); 269 | } 270 | } 271 | 272 | class Psr4AutoloaderClassTest extends \PHPUnit_Framework_TestCase 273 | { 274 | protected $loader; 275 | 276 | protected function setUp() 277 | { 278 | $this->loader = new MockPsr4AutoloaderClass; 279 | 280 | $this->loader->setFiles(array( 281 | '/vendor/foo.bar/src/ClassName.php', 282 | '/vendor/foo.bar/src/DoomClassName.php', 283 | '/vendor/foo.bar/tests/ClassNameTest.php', 284 | '/vendor/foo.bardoom/src/ClassName.php', 285 | '/vendor/foo.bar.baz.dib/src/ClassName.php', 286 | '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php', 287 | )); 288 | 289 | $this->loader->addNamespace( 290 | 'Foo\Bar', 291 | '/vendor/foo.bar/src' 292 | ); 293 | 294 | $this->loader->addNamespace( 295 | 'Foo\Bar', 296 | '/vendor/foo.bar/tests' 297 | ); 298 | 299 | $this->loader->addNamespace( 300 | 'Foo\BarDoom', 301 | '/vendor/foo.bardoom/src' 302 | ); 303 | 304 | $this->loader->addNamespace( 305 | 'Foo\Bar\Baz\Dib', 306 | '/vendor/foo.bar.baz.dib/src' 307 | ); 308 | 309 | $this->loader->addNamespace( 310 | 'Foo\Bar\Baz\Dib\Zim\Gir', 311 | '/vendor/foo.bar.baz.dib.zim.gir/src' 312 | ); 313 | } 314 | 315 | public function testExistingFile() 316 | { 317 | $actual = $this->loader->loadClass('Foo\Bar\ClassName'); 318 | $expect = '/vendor/foo.bar/src/ClassName.php'; 319 | $this->assertSame($expect, $actual); 320 | 321 | $actual = $this->loader->loadClass('Foo\Bar\ClassNameTest'); 322 | $expect = '/vendor/foo.bar/tests/ClassNameTest.php'; 323 | $this->assertSame($expect, $actual); 324 | } 325 | 326 | public function testMissingFile() 327 | { 328 | $actual = $this->loader->loadClass('No_Vendor\No_Package\NoClass'); 329 | $this->assertFalse($actual); 330 | } 331 | 332 | public function testDeepFile() 333 | { 334 | $actual = $this->loader->loadClass('Foo\Bar\Baz\Dib\Zim\Gir\ClassName'); 335 | $expect = '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php'; 336 | $this->assertSame($expect, $actual); 337 | } 338 | 339 | public function testConfusion() 340 | { 341 | $actual = $this->loader->loadClass('Foo\Bar\DoomClassName'); 342 | $expect = '/vendor/foo.bar/src/DoomClassName.php'; 343 | $this->assertSame($expect, $actual); 344 | 345 | $actual = $this->loader->loadClass('Foo\BarDoom\ClassName'); 346 | $expect = '/vendor/foo.bardoom/src/ClassName.php'; 347 | $this->assertSame($expect, $actual); 348 | } 349 | } 350 | ~~~ 351 | -------------------------------------------------------------------------------- /accepted/PSR-4-autoloader-meta.md: -------------------------------------------------------------------------------- 1 | # PSR-4 Meta Document 2 | 3 | ## 1. Summary 4 | 5 | The purpose is to specify the rules for an interoperable PHP autoloader that 6 | maps namespaces to file system paths, and that can co-exist with any other SPL 7 | registered autoloader. This would be an addition to, not a replacement for, 8 | PSR-0. 9 | 10 | ## 2. Why Bother? 11 | 12 | ### History of PSR-0 13 | 14 | The PSR-0 class naming and autoloading standard rose out of the broad 15 | acceptance of the Horde/PEAR convention under the constraints of PHP 5.2 and 16 | previous. With that convention, the tendency was to put all PHP source classes 17 | in a single main directory, using underscores in the class name to indicate 18 | pseudo-namespaces, like so: 19 | 20 | /path/to/src/ 21 | VendorFoo/ 22 | Bar/ 23 | Baz.php # VendorFoo_Bar_Baz 24 | VendorDib/ 25 | Zim/ 26 | Gir.php # Vendor_Dib_Zim_Gir 27 | 28 | With the release of PHP 5.3 and the availability of namespaces proper, PSR-0 29 | was introduced to allow both the old Horde/PEAR underscore mode *and* the use 30 | of the new namespace notation. Underscores were still allowed in the class 31 | name to ease the transition from the older namespace naming to the newer naming, 32 | and thereby to encourage wider adoption. 33 | 34 | /path/to/src/ 35 | VendorFoo/ 36 | Bar/ 37 | Baz.php # VendorFoo_Bar_Baz 38 | VendorDib/ 39 | Zim/ 40 | Gir.php # VendorDib_Zim_Gir 41 | Irk_Operation/ 42 | Impending_Doom/ 43 | V1.php 44 | V2.php # Irk_Operation\Impending_Doom\V2 45 | 46 | This structure is informed very much by the fact that the PEAR installer moved 47 | source files from PEAR packages into a single central directory. 48 | 49 | ### Along Comes Composer 50 | 51 | With Composer, package sources are no longer copied to a single global 52 | location. They are used from their installed location and are not moved 53 | around. This means that with Composer there is no "single main directory" for 54 | PHP sources as with PEAR. Instead, there are multiple directories; each 55 | package is in a separate directory for each project. 56 | 57 | To meet the requirements of PSR-0, this leads to Composer packages looking 58 | like this: 59 | 60 | vendor/ 61 | vendor_name/ 62 | package_name/ 63 | src/ 64 | Vendor_Name/ 65 | Package_Name/ 66 | ClassName.php # Vendor_Name\Package_Name\ClassName 67 | tests/ 68 | Vendor_Name/ 69 | Package_Name/ 70 | ClassNameTest.php # Vendor_Name\Package_Name\ClassNameTest 71 | 72 | The "src" and "tests" directories have to include vendor and package directory 73 | names. This is an artifact of PSR-0 compliance. 74 | 75 | Many find this structure to be deeper and more repetitive than necessary. This 76 | proposal suggests that an additional or superseding PSR would be useful so 77 | that we can have packages that look more like the following: 78 | 79 | vendor/ 80 | vendor_name/ 81 | package_name/ 82 | src/ 83 | ClassName.php # Vendor_Name\Package_Name\ClassName 84 | tests/ 85 | ClassNameTest.php # Vendor_Name\Package_Name\ClassNameTest 86 | 87 | This would require an implementation of what was initially called 88 | "package-oriented autoloading" (as vs the traditional "direct class-to-file 89 | autoloading"). 90 | 91 | ### Package-Oriented Autoloading 92 | 93 | It's difficult to implement package-oriented autoloading via an extension or 94 | amendment to PSR-0, because PSR-0 does not allow for an intercessory path 95 | between any portions of the class name. This means the implementation of a 96 | package-oriented autoloader would be more complicated than PSR-0. However, it 97 | would allow for cleaner packages. 98 | 99 | Initially, the following rules were suggested: 100 | 101 | 1. Implementors MUST use at least two namespace levels: a vendor name, and 102 | package name within that vendor. (This top-level two-name combination is 103 | hereinafter referred to as the vendor-package name or the vendor-package 104 | namespace.) 105 | 106 | 2. Implementors MUST allow a path infix between the vendor-package namespace 107 | and the remainder of the fully qualified class name. 108 | 109 | 3. The vendor-package namespace MAY map to any directory. The remaining 110 | portion of the fully-qualified class name MUST map the namespace names to 111 | identically-named directories, and MUST map the class name to an 112 | identically-named file ending in .php. 113 | 114 | Note that this means the end of underscore-as-directory-separator in the class 115 | name. One might think underscores should be honored as they are under 116 | PSR-0, but seeing as their presence in that document is in reference to 117 | transitioning away from PHP 5.2 and previous pseudo-namespacing, it is 118 | acceptable to remove them here as well. 119 | 120 | ## 3. Scope 121 | 122 | ### 3.1 Goals 123 | 124 | - Retain the PSR-0 rule that implementors MUST use at least two namespace 125 | levels: a vendor name, and package name within that vendor. 126 | 127 | - Allow a path infix between the vendor-package namespace and the remainder of 128 | the fully qualified class name. 129 | 130 | - Allow the vendor-package namespace MAY map to any directory, perhaps 131 | multiple directories. 132 | 133 | - End the honoring of underscores in class names as directory separators 134 | 135 | ### 3.2 Non-Goals 136 | 137 | - Provide a general transformation algorithm for non-class resources 138 | 139 | ## 4. Approaches 140 | 141 | ### 4.1 Chosen Approach 142 | 143 | This approach retains key characteristics of PSR-0 while eliminating the 144 | deeper directory structures it requires. In addition, it specifies certain 145 | additional rules that make implementations explicitly more interoperable. 146 | 147 | Although not related to directory mapping, the final draft also specifies how 148 | autoloaders should handle errors. Specifically, it forbids throwing exceptions 149 | or raising errors. The reason is two-fold. 150 | 151 | 1. Autoloaders in PHP are explicitly designed to be stackable so that if one 152 | autoloader cannot load a class another has a chance to do so. Having an autoloader 153 | trigger a breaking error condition violates that compatibility. 154 | 155 | 2. `class_exists()` and `interface_exists()` allow "not found, even after trying to 156 | autoload" as a legitimate, normal use case. An autoloader that throws exceptions 157 | renders `class_exists()` unusable, which is entirely unacceptable from an interoperability 158 | standpoint. Autoloaders that wish to provide additional debugging information 159 | in a class-not-found case should do so via logging instead, either to a PSR-3 160 | compatible logger or otherwise. 161 | 162 | Pros: 163 | 164 | - Shallower directory structures 165 | 166 | - More flexible file locations 167 | 168 | - Stops underscore in class name from being honored as directory separator 169 | 170 | - Makes implementations more explicitly interoperable 171 | 172 | Cons: 173 | 174 | - It is no longer possible, as under PSR-0, to merely examine a class name to 175 | determine where it is in the file system (the "class-to-file" convention 176 | inherited from Horde/PEAR). 177 | 178 | ### 4.2 Alternative: Stay With PSR-0 Only 179 | 180 | Staying with PSR-0 only, although reasonable, does leave us with relatively 181 | deeper directory structures. 182 | 183 | Pros: 184 | 185 | - No need to change anyone's habits or implementations 186 | 187 | Cons: 188 | 189 | - Leaves us with deeper directory structures 190 | 191 | - Leaves us with underscores in the class name being honored as directory 192 | separators 193 | 194 | ### 4.3 Alternative: Split Up Autoloading And Transformation 195 | 196 | Beau Simensen and others suggested that the transformation algorithm might be 197 | split out from the autoloading proposal so that the transformation rules 198 | could be referenced by other proposals. After doing the work to separate them, 199 | followed by a poll and some discussion, the combined version (i.e., 200 | transformation rules embedded in the autoloader proposal) was revealed as the 201 | preference. 202 | 203 | Pros: 204 | 205 | - Transformation rules could be referenced separately by other proposals 206 | 207 | Cons: 208 | 209 | - Not in line with the wishes of poll respondents and some collaborators 210 | 211 | ### 4.4 Alternative: Use More Imperative And Narrative Language 212 | 213 | After the second vote was pulled by a Sponsor after hearing from multiple +1 214 | voters that they supported the idea but did not agree with (or understand) the 215 | wording of the proposal, there was a period during which the voted-on proposal 216 | was expanded with greater narrative and somewhat more imperative language. This 217 | approach was decried by a vocal minority of participants. After some time, Beau 218 | Simensen started an experimental revision with an eye to PSR-0; the Editor and 219 | Sponsors favored this more terse approach and shepherded the version now under 220 | consideration, written by Paul M. Jones and contributed to by many. 221 | 222 | ### Compatibility Note with PHP 5.3.2 and below 223 | 224 | PHP versions before 5.3.3 do not strip the leading namespace separator, so 225 | the responsibility to look out for this falls on the implementation. Failing 226 | to strip the leading namespace separator could lead to unexpected behavior. 227 | 228 | ## 5. People 229 | 230 | ### 5.1 Editor 231 | 232 | - Paul M. Jones, Solar/Aura 233 | 234 | ### 5.2 Sponsors 235 | 236 | - Phil Sturgeon, PyroCMS (Coordinator) 237 | - Larry Garfield, Drupal 238 | 239 | ### 5.3 Contributors 240 | 241 | - Andreas Hennings 242 | - Bernhard Schussek 243 | - Beau Simensen 244 | - Donald Gilbert 245 | - Mike van Riel 246 | - Paul Dragoonis 247 | - Too many others to name and count 248 | 249 | ## 6. Votes 250 | 251 | - **Entrance Vote:** 252 | 253 | - **Acceptance Vote:** 254 | 255 | - 1st attempt: , 256 | presented prior to new workflow; aborted due to accidental proposal modification 257 | 258 | - 2nd attempt: , 259 | cancelled at the discretion of the sponsor 260 | 261 | - 3rd attempt: TBD 262 | 263 | ## 7. Relevant Links 264 | 265 | - [Autoloader, round 4](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/lpmJcmkNYjM) 266 | - [POLL: Autoloader: Split or Combined?](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/fGwA6XHlYhI) 267 | - [PSR-X autoloader spec: Loopholes, ambiguities](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/kUbzJAbHxmg) 268 | - [Autoloader: Combine Proposals?](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/422dFBGs1Yc) 269 | - [Package-Oriented Autoloader, Round 2](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/Y4xc71Q3YEQ) 270 | - [Autoloader: looking again at namespace](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/bnoiTxE8L28) 271 | - [DISCUSSION: Package-Oriented Autoloader - vote against](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/SJTL1ec46II) 272 | - [VOTE: Package-Oriented Autoloader](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/Ua46E344_Ls) 273 | - [Proposal: Package-Oriented Autoloader](https://groups.google.com/forum/#!topicsearchin/php-fig/autoload/php-fig/qT7mEy0RIuI) 274 | - [Towards a Package Oriented Autoloader](https://groups.google.com/forum/#!searchin/php-fig/package$20oriented$20autoloader/php-fig/JdR-g8ZxKa8/jJr80ard-ekJ) 275 | - [List of Alternative PSR-4 Proposals](https://groups.google.com/forum/#!topic/php-fig/oXr-2TU1lQY) 276 | - [Summary of [post-Acceptance Vote pull] PSR-4 discussions](https://groups.google.com/forum/#!searchin/php-fig/psr-4$20summary/php-fig/bSTwUX58NhE/YPcFgBjwvpEJ) 277 | -------------------------------------------------------------------------------- /accepted/PSR-4-autoloader.md: -------------------------------------------------------------------------------- 1 | # Autoloader 2 | 3 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 4 | "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 5 | interpreted as described in [RFC 2119](http://tools.ietf.org/html/rfc2119). 6 | 7 | ## 1. Overview 8 | 9 | This PSR describes a specification for [autoloading][] classes from file 10 | paths. It is fully interoperable, and can be used in addition to any other 11 | autoloading specification, including [PSR-0][]. This PSR also describes where 12 | to place files that will be autoloaded according to the specification. 13 | 14 | ## 2. Specification 15 | 16 | 1. The term "class" refers to classes, interfaces, traits, and other similar 17 | structures. 18 | 19 | 2. A fully qualified class name has the following form: 20 | 21 | \(\)*\ 22 | 23 | 1. The fully qualified class name MUST have a top-level namespace name, 24 | also known as a "vendor namespace". 25 | 26 | 2. The fully qualified class name MAY have one or more sub-namespace 27 | names. 28 | 29 | 3. The fully qualified class name MUST have a terminating class name. 30 | 31 | 4. Underscores have no special meaning in any portion of the fully 32 | qualified class name. 33 | 34 | 5. Alphabetic characters in the fully qualified class name MAY be any 35 | combination of lower case and upper case. 36 | 37 | 6. All class names MUST be referenced in a case-sensitive fashion. 38 | 39 | 3. When loading a file that corresponds to a fully qualified class name ... 40 | 41 | 1. A contiguous series of one or more leading namespace and sub-namespace 42 | names, not including the leading namespace separator, in the fully 43 | qualified class name (a "namespace prefix") corresponds to at least one 44 | "base directory". 45 | 46 | 2. The contiguous sub-namespace names after the "namespace prefix" 47 | correspond to a subdirectory within a "base directory", in which the 48 | namespace separators represent directory separators. The subdirectory 49 | name MUST match the case of the sub-namespace names. 50 | 51 | 3. The terminating class name corresponds to a file name ending in `.php`. 52 | The file name MUST match the case of the terminating class name. 53 | 54 | 4. Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors 55 | of any level, and SHOULD NOT return a value. 56 | 57 | ## 3. Examples 58 | 59 | The table below shows the corresponding file path for a given fully qualified 60 | class name, namespace prefix, and base directory. 61 | 62 | | Fully Qualified Class Name | Namespace Prefix | Base Directory | Resulting File Path 63 | | ----------------------------- |--------------------|--------------------------|------------------------------------------- 64 | | \Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php 65 | | \Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php 66 | | \Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php 67 | | \Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php 68 | 69 | For example implementations of autoloaders conforming to the specification, 70 | please see the [examples file][]. Example implementations MUST NOT be regarded 71 | as part of the specification and MAY change at any time. 72 | 73 | [autoloading]: http://php.net/autoload 74 | [PSR-0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 75 | [examples file]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md 76 | -------------------------------------------------------------------------------- /bylaws/002-psr-workflow.md: -------------------------------------------------------------------------------- 1 | # PHP Standard Recommendation (PSR) Workflow 2 | 3 | ## Pre-Draft 4 | 5 | The goal of the Pre-Draft stage is to determine whether a majority of the PHP FIG is interested in publishing a PSR for a proposed concept. 6 | 7 | Interested parties may discuss a possible proposal, including possible implementations, by whatever means they feel is appropriate. That includes informal discussion on official FIG discussion mediums of whether or not the idea has merit and is within the scope of the PHP FIG's goals. 8 | 9 | Once those parties have determined to move forward, they must form a Full Working Group. 10 | 11 | The proposal is not required to be fully developed at this point, although that is permitted. At minimum, it must include a statement of the problem to be solved and basic information on the general approach to be taken. Further revision and expansion is expected during the Draft Phase. 12 | 13 | The Sponsor may then call for an Entrance Vote of the Core Committee to enquire whether the Core Committee is generally interested in publishing a PSR for the proposed subject, even if they disagree with the details of the proposal. 14 | 15 | If the vote passes, the proposal officially enters Draft stage. The proposal receives a PSR number incremented from the highest numbered PSR which has passed the Entrance Vote, regardless of the status of that PSR. 16 | 17 | The Working Group may continue to work on the proposal during the complete voting period. 18 | 19 | ## Draft 20 | 21 | The goal of the Draft stage is to discuss and polish a PSR proposal up to the point that it can be considered for review by the FIG Core Committee. 22 | 23 | In Draft stage, members of the Working Group may make any changes they see fit via pull requests, comments on GitHub, Mailing List threads, chat, and similar tools. Change here is not limited by any strict rules, and fundamental rewrites are possible if supported by the Editor. Alternative approaches may be proposed and discussed at any time. If the Editor and Sponsor are convinced that an alternative proposal is superior to the original proposal, then the alternative may replace the original. Working Group members are expected to remain engaged throughout the Draft Phase. Discussions are public and anyone, regardless of FIG affiliation, is welcome to offer constructive input. During this phase, the Editor has final authority on changes made to the proposed specification. 24 | 25 | All knowledge gained during Draft stage, such as possible alternative approaches, their implications, pros and cons etc. as well as the reasons for choosing the proposed approach must be summarized in the meta document. The purpose of this rule is to prevent circular discussions or alternative proposals from reappearing once they have been decided upon. 26 | 27 | When the Editor and Sponsor agree that the proposal is ready and that the meta document is objective and complete, the Editor may call for a Readiness Vote of the Working Group to determine if the specification is substantively complete and ready for trial implementations. 28 | 29 | If the vote passes, the proposal officially enters Review Phase. If it does not, it remains in Draft Phase. 30 | 31 | ## Review 32 | 33 | The Review Phase is an opportunity for the community to experiment with a reasonably fixed target to evaluate a proposal's practicality. At this stage, the Sponsor is the final authority on changes to the specification as well as any decisions to move the proposal forward or backward, however, the Editor may veto proposed changes they believe are harmful to the design of the specification. 34 | 35 | During this phase, trial implementations of the specification are expected and encouraged. Changes to the specification are limited to those directly informed by trial implementations, wording, typos, clarification, etc. Major changes are not permitted in this phase. If the development of trial implementations demonstrates the need for major changes then the specification must be pushed back to Draft Phase. Any incompatible change that would require significant effort for trial implementations to adjust for qualifies as a major change. Small to moderate incompatible changes do not necessarily mandate a return to Draft Phase. 36 | 37 | Unless a proposal is moved to Draft stage again, it must remain in Review stage for a minimum of four weeks and until two independent viable trial implementations can be demonstrated. The responsibility for finding such trial implementations and presenting them to the Core Committee lies with the Working Group, and especially the Editor and Sponsor. As not all specifications are PHP interfaces where the definition of "implementation" is self-evident, the Sponsor should use good faith judgement to determine when that is the case. Any member of the Core Committee may object to a given trial implementation as irrelevant or insufficient with due cause. 38 | 39 | Once four weeks have passed and two viable trial implementations can be demonstrated, the Sponsor may call an Acceptance Vote. If the Acceptance Vote fails, the specification may remain in Review. 40 | 41 | ## Accepted 42 | 43 | If the Acceptance Vote passes, then the proposal officially becomes an accepted PSR. At this time the Working Group is automatically dissolved. The Editor of the PSR automatically becomes the Maintainer of the specification should typos, changes or Errata on the specification be raised. The Editor is also automatically the Maintainer of any artifacts the Working Group has produced, such as utility libraries. 44 | 45 | ## Erratas 46 | 47 | If an incongruence or the need for clarifications arise after the PSR acceptance, it is still possible to amend the document with an errata. The Maintainer of the PSR has the power to handle those situations, but any meaningful change has to go through an Errata vote before merging. Typos and any other edits that do not change the meaning of the text do not fall in this category, and can be merged by the Secretaries at will. 48 | 49 | Errata clarifications may only be added to the meta document, not to the spec itself, as items in their own section. The spec itself may only be minimally edited to point readers toward a relevant errata if appropriate. 50 | 51 | ## Deprecated 52 | 53 | A Deprecated PSR is one that has been approved, but is no longer considered relevant or recommended. Typically, this is due to the PSR being superseded by a new version, but that is not required. 54 | 55 | A PSR may be Deprecated explicitly as part of the Acceptance Vote for another PSR. Alternatively, it may be marked Deprecated by a Deprecation Vote. 56 | 57 | ## Abandoned 58 | 59 | An Abandoned PSR is one that is not actively being worked upon. Should the Working Group for the PSR be dissolved, the PSR is automatically marked as Abandoned. 60 | 61 | Once a PSR is in "Abandoned" stage it may only once again be moved to Draft after a fresh Entrance vote by the Core Committee following the same procedure as if it was a pre-draft, except it may retain its previously assigned number. If the aims of the PSR differ from the original entrance vote, it is up to the discretion of the Core Committee whether it should be considered a fresh PSR or a restart of activity on the Abandoned PSR. 62 | 63 | ## Project Referendum 64 | 65 | At any time the Editor of a PSR in Draft or Review Phase may call for a non-binding Referendum of Project Representatives on the current state of a PSR. Such a Referendum may be called multiple times if appropriate as the PSR evolves, or never, at the Editor's discretion. The Core Committee may also require such a Referendum as a condition of an Acceptance Vote if appropriate. Referendum results are non-binding but the Working Group and Core Committee are expected to give the results due consideration. 66 | -------------------------------------------------------------------------------- /bylaws/003-per-workflow.md: -------------------------------------------------------------------------------- 1 | # PHP Evolving Recommendation Workflow 2 | 3 | ## Formation 4 | 5 | The goal of the Formation stage is to determine whether a majority of the PHP FIG is interested in establishing a PER Working Group for a proposed concept. 6 | 7 | Interested parties may discuss a possible proposal, including possible implementations, by whatever means they feel is appropriate. That includes informal discussion on official FIG discussion mediums of whether or not the idea has merit and is within the scope of the PHP FIG's goals. 8 | 9 | Once those parties have determined to move forward, they must form a Limited Working Group. However, the Core Committee may require that a specific PER requires a Full Working Group in cases of particularly high impact to the larger ecosystem in order to encourage greater community participation. 10 | 11 | The proposal is not required to be fully developed at this point, although that is permitted. At minimum, it must include a statement of the problem to be solved, the scope of the PER Working Group, and the artifacts it expects to produce. 12 | 13 | The Editor (for a Limited Working Group) or Sponsor (for a Full Working Group) may then call for an Entrance Vote of the Core Committee to enquire whether the Core Committee is generally interested in maintaining a PER for the proposed subject, even if they disagree with the details of the proposal. 14 | 15 | If the vote passes, the proposal officially enters Draft stage. The proposal is given a unique descriptive name (such as "Coding Standards", "Documentation", etc.). 16 | 17 | ## Development 18 | 19 | Once established, the PER Working Group may collaborate in whatever way they see fit via pull requests, comments on GitHub, Mailing List threads, real-time chat, and similar tools. The Working Group must maintain a meta document including considered but rejected approaches, the reasons for various decisions, etc. The meta document is considered part of the Working Group's output, and must be tagged along with the main artifacts of the Working Group. 20 | 21 | Discussions are public and anyone, regardless of FIG affiliation, is welcome to offer constructive input. The Editor has final authority on changes made to the Working Group's output. 22 | 23 | ## Pre-Releases 24 | 25 | Prior to the 1.0.0 release of the PER, the Editor may make alpha, beta, or 0.x releases of any artifact at any time. These releases are explicitly unstable, and MUST be treated as unsupported by FIG or the Working Group. They are not subject to Core Committee approval. 26 | 27 | ## Releases 28 | 29 | The Editor of a PER artifact may release bugfix releases at any time. 30 | 31 | For any new release that would be minor or major according to Semantic Versioning (whether text or code), the Editor must first call for a Readiness Vote of the Working Group. If the Readiness Vote passes, the Editor in capacity as Maintainer may inform the Core Committee of an Intent to Release as specified in the Maintainers section. 32 | 33 | The Core Committee must approve any major releases from 1.0.0 onwards. 34 | -------------------------------------------------------------------------------- /bylaws/004-votes.md: -------------------------------------------------------------------------------- 1 | # Votes 2 | 3 | There are a number of different types of vote, each of which has its own rule set and expected threshold. Unless otherwise specified, all votes take place over a period of two weeks, or until all eligible voters have voted, whichever comes first, and votes are public. Explicit abstentions (+0) will count toward quorum, if applicable, but do not count toward majority. 4 | 5 | Non-trivial votes should be preceded by at least two weeks of discussion, although no formal discussion mechanism is required. 6 | 7 | The mechanics of voting (email, forum, any conventional subject lines, etc.) may be established and publicized by the Secretaries. 8 | 9 | Votes may be changed at will until the end of the voting period. 10 | 11 | In some cases, votes may overlap such that an individual would become eligible to cast a vote only as a result of another overlapping vote, such as a membership vote. In all cases, eligibility to vote will be defined based on membership at the moment a given vote starts. For nominations for Secretary or Core Committee member, eligibility to vote will be defined based on membership at the moment the nominating period begins. 12 | 13 | A secretary may trigger any type of vote if appropriate and necessary. 14 | 15 | Rounding of quorums and majorities would occur such that: 16 | 17 | * A vote requiring a quorum of 1/3 of an electorate of 20, 21 or 22 members would require 7 votes to be cast 18 | * A vote requiring a quorum of 1/3 of an electorate of 23, 24 or 25 members would require 8 votes to be cast 19 | * A vote requiring a 50% majority with 10 or 11 votes cast would require 6 or more to be in favour to pass 20 | * A vote requiring a 50% majority with 12 or 13 votes cast would require 7 or more to be in favour to pass 21 | 22 | ## Vote Types 23 | 24 | Most votes are held by the Core Committee, and fall into one of two categories: Approval or Decision. Unless otherwise specified, any member of the Core Committee or a Secretary may call an Approval or Decision Vote. 25 | 26 | ### Approval Vote 27 | 28 | An Approval Vote is a yes-or-no question, in which case the status quo (voting "no") produces a stable outcome. Only Core Committee members may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 2/3 majority is required for passage. 29 | 30 | ### Decision Vote 31 | 32 | A Decision Vote is used to select between two or more mutually-exclusive courses of action, in which case the status quo is not stable (e.g., a vacancy is being filled). Only Core Committee members may vote. A Decision Vote will be conducted using Single Transferable Vote with a single-winner. Quorum is 50%. 33 | 34 | ## Entrance Vote 35 | 36 | An Entrance Vote is called by the Sponsor of a proposed PSR. It follows Approval Vote procedures. 37 | 38 | ## Readiness Vote 39 | 40 | A Readiness Vote is called by the Editor of a proposed PSR in Draft Phase. Only members of the PSR's Working Group (including the Editor and Sponsor) may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 2/3 majority is required for passage. 41 | 42 | ## Acceptance Vote 43 | 44 | An Acceptance Vote is called by the Sponsor of a proposed PSR in the Review Phase. It follows Approval Vote procedures. 45 | 46 | ## Errata Vote 47 | 48 | An Errata Vote is called by the Editor of an approved PSR, or a Secretary if the Editor is no longer available. It follows Approval Vote procedures. 49 | 50 | ## Deprecation Vote 51 | 52 | A Deprecation Vote is called by any Core Committee Member. It follows Approval Vote procedures. 53 | 54 | ## Abandonment Vote 55 | 56 | An Abandonment Vote is called by any Secretary or Core Committee Member. It follows Approval Vote procedures. 57 | 58 | ## Implicit Approval 59 | 60 | At times, routine Working Group activity is subject to the approval of the Core Committee but in most cases is not sufficiently controversial to warrant a full vote. In such cases, an individual may declare an Intent to take an action. If no member of the Core Committee objects within seven days, the action is implicitly approved. 61 | 62 | Any member of the Core Committee may request during that seven-day period that the change be put to a vote. If any member does so, the action is put to an Approval Vote or Decision Vote (as appropriate to the situation) to determine if it is accepted or not. 63 | 64 | ## Membership Vote 65 | 66 | A Membership Vote is called by any Project Representative and consists of a separate concurrent vote by the Core Committee and Project Representatives. 67 | 68 | For the Core Committee vote, Core Committee members may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 50% majority is required for passage. 69 | 70 | For the Project Representative vote, Project Representatives may vote, either For (+1), Against (-1), or Abstain (+0). There is no quorum. A 50% majority is required for passage. 71 | 72 | Both the Core Committee and Project Representative votes must pass for the Membership Vote to be approved. If an individual is serving as both a Project Representative and Core Committee member, they are ineligible to vote in the Project Representative vote. If an individual is on the Core Committee and they are to be the Project Represenative for the project in question, they are not eligible to vote. 73 | 74 | ## Expulsion vote 75 | 76 | An Expulsion Vote is called by any Secretary or Core Committee member and consists of a separate concurrent vote by the Core Committee and Project Representatives. 77 | 78 | For the Core Committee vote, Core Committee members may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 50% majority is required for passage. 79 | 80 | For the Project Representative vote, Project Representatives may vote, either For (+1), Against (-1), or Abstain (+0). There is no quorum. A 50% majority is required for passage. 81 | 82 | Both the Core Committee and Project Representative votes must pass for the Expulsion Vote to be approved. If an individual is serving as both a Project Representative and Core Committee member, they are ineligible to vote in the Project Representative vote. The Project Representative that is the subject, or whose project is the subject, of the Expulsion Vote is not eligible to vote. 83 | 84 | ## Recall Vote 85 | 86 | A Recall Vote is called by any two of a Secretary, Core Committee member, and Project Representative, and consists of a separate concurrent vote by the Core Committee and Project Representatives. 87 | 88 | For the Core Committee vote, Core Committee members may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 2/3 majority is required for passage. 89 | 90 | For the Project Representative vote, Project Representatives may vote, either For (+1), Against (-1), or Abstain (+0). There is no quorum. A 2/3 majority is required for passage. 91 | 92 | Both the Core Committee and Project Representative votes must pass for the Recall Vote to be approved. If an individual is serving as both a Project Representative and Core Committee member, they are ineligible to vote in the Project Representative vote. If a Core Committee member is the subject of the Recall Vote, they are not eligible to vote. 93 | 94 | ## Bylaw Votes 95 | 96 | A vote to amend any FIG bylaw is called by a Secretary, and consists of a separate concurrent vote by the Core Committee and Project Representatives. 97 | 98 | For the Core Committee vote, Core Committee members may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 2/3 majority is required for passage. 99 | 100 | For the Project Representative vote, Project Representatives may vote, either For (+1), Against (-1), or Abstain (+0). There is no quorum. A 2/3 majority is required for passage. 101 | 102 | Both the Core Committee and Project Representative votes must pass for the Bylaw Vote to be approved. If an individual is serving as both a Project Representative and Core Committee member, they are ineligible to vote in the Project Representative vote. 103 | 104 | ## Other Votes 105 | 106 | Should a need arise to call a formal vote for any situation not described here, the vote will be called by a Secretary. It consists of a separate vote by the Core Committee and Project Representatives. 107 | 108 | For the Core Committee vote, Core Committee members may vote, either For (+1), Against (-1), or Abstain (+0). Quorum is 50%. A 2/3 majority is required for passage. 109 | 110 | For the Project Representative vote, Project Representatives may vote, either For (+1), Against (-1), or Abstain (+0). There is no quorum. A 50% majority is required for passage. 111 | 112 | Both the Core Committee and Project Representative votes must pass for the Vote to be approved. If an individual is serving as both a Project Representative and Core Committee member, they are ineligible to vote in the Project Representative vote. 113 | -------------------------------------------------------------------------------- /bylaws/005-elections-and-vacancies.md: -------------------------------------------------------------------------------- 1 | # Elections 2 | 3 | ## Election Calendar 4 | 5 | Both Secretaries and Core Committee members are elected for two year terms with votes staggered eight months apart. One election is held in January of even numbered years, one election is held in August of even numbered years, and one election is held in May of odd numbered years. For example there would be elections in January 2018, August 2018 and May 2019. Each regular election includes a single Secretary and four (4) Core Committee members, plus any potential unplanned vacancies. 6 | 7 | The election calendar will be established by the Secretaries at least one week before the start of the election month. Nominations must run for a minimum of seven (7) days. The vote will open immediately upon the end of the nomination period and must run for fourteen (14) days. The new Secretary and Core Committee members will take office at 5pm UTC time on the last Sunday of the month, and the voting period must conclude at least 24 hours prior to that. 8 | 9 | The election process will be overseen by either of the Secretaries whose term is not expiring, and both the Secretary and Core Committee elections may be overseen by the same Secretary or different Secretaries. 10 | 11 | ## Eligibility 12 | 13 | Any individual may run for election as Secretary, including the outgoing Secretary. If they are a Core Committee Member or PSR Editor and are elected they must resign between the vote ending and taking office. 14 | 15 | Any individual may run for election as a Core Committee member, including the outgoing Core Committee member. If they are a Secretary and are elected they must resign between the vote ending and taking office. 16 | 17 | ## Nomination 18 | 19 | Candidates for Secretary or the Core Committee must be nominated/proposed by an existing Project Representative or FIG Secretary to be considered, and must publicly accept their nomination in order to be valid. Prospective candidates may seek nominations in any way they see fit. 20 | 21 | ## Electorate 22 | 23 | Any Project Representative or Core Committee member is eligible to to vote on Secretary candidates. 24 | 25 | Any individual that has posted a non-trivial message in the official FIG venue (mailing list, forum, etc.) at least five (5) times within the past calendar year as of the start of nominations or any Project Representative is eligible to vote on Core Committee candidates. 26 | 27 | The Secretaries whose terms are not expiring have final jurisdiction to determine eligibility. 28 | 29 | ## Voting 30 | 31 | The election will be conducted using Single Transferable Vote with specific algorithms being maintained by the Secretaries. If multiple seats are open (either for Core Committee membership or due to a vacancy) then the open seats with the longest term will go to first candidate(s) to reach the required quota. 32 | 33 | ## Recall Votes 34 | 35 | Should a Secretary or Core Committee member be determined to be acting with gross negligence or in a way that undermines the FIG's mission or good standing, a Recall Vote may be called by any two of a Secretary, Core Committee member, and Project Representative. Any such vote must be preceded by at least a two week discussion period. The vote will be overseen by a Secretary other than the subject of the Recall Vote. Should the vote pass the individual in question is removed immediately. If it does not pass the matter is considered closed and a new vote may not be called for the same incident, if applicable. 36 | 37 | # Vacancies 38 | 39 | ## Editor Vacancies 40 | 41 | Should the Editor of a PSR under consideration resign or become inactive for a period of 60 days, the Sponsor may select a new Editor subject to rejection by the Core Committee. Current members of the Working Group should be given preference. If no new Editor is named within 30 days from the vacancy notice then the PSR can be marked as Abandoned. 42 | 43 | ## Sponsor Vacancies 44 | 45 | Should the Sponsor of a PSR under consideration resign or become inactive for a period of 60 days, the Editor may select a new Sponsor subject to rejection by the Core Committee. If no new Sponsor is named within 30 days from the vacancy notice then the PSR can become Abandoned. 46 | 47 | ## Secretary Vacancies 48 | 49 | Should a Secretary resign or be removed due to a Recall vote, an existing Secretary shall call a special election for a new Secretary following the same protocols as for a normal election. The newly elected Secretary will serve out the remainder of the term for the seat filled. 50 | 51 | Should the vacancy occur less than four months before the next regular election month, the seat may be left vacant until the next election at the discretion of the other Secretaries and Core Committee. In that case, the second-highest voted candidate will assume the available seat with less time remaining in its term. Should two Secretary positions become vacant simultaneously a special election must be called immediately for both seats. 52 | 53 | ## Core Committee Vacancy 54 | 55 | Should a Core Committee member resign or be removed due to a Recall Vote, the Secretaries shall call a special election for a new Core Committee member following the same protocols as for a normal election. The newly elected Core Committee member will serve out the remainder of the term for the seat filled. 56 | 57 | Should the vacancy occur less than four months before the next regular election month, the seat may be left vacant until the next election at the discretion of the Secretaries and Core Committee. In that case, the fifth-highest voted candidate will assume the available seat with less time remaining in its term. 58 | -------------------------------------------------------------------------------- /bylaws/006-licensing-policies.md: -------------------------------------------------------------------------------- 1 | Licensing Policies 2 | ================== 3 | 4 | ## 1. Code 5 | 6 | 1. All PHP FIG code must be licensed under the MIT license. 7 | 8 | 2. Code includes any pure PHP files (including but not limited to classes, 9 | functions, interfaces and procedural code), as well as any code inside of 10 | examples, tutorials, supporting documents, website code and the PSRs themselves. 11 | 12 | ## 2. Documentation 13 | 14 | All remaining non-code items must be licensed under the Creative Commons BY 3.0 15 | license. Attribution policies will be defined in the bylaws based on the type 16 | of asset created. 17 | -------------------------------------------------------------------------------- /bylaws/007-psr-amendments.md: -------------------------------------------------------------------------------- 1 | Amendments 2 | ========== 3 | 4 | Following the rules of the [workflow bylaw], once a PSR has been "Accepted" the PSR meaning 5 | cannot change, backwards compatibility must remain at 100%, and any confusion that arises from 6 | original wording can be clarified through errata. 7 | 8 | The rules for errata are covered in the [workflow bylaw], and only allow non-backwards compatible 9 | clarification to be added to the meta document. Sometimes, modifications will be necessary in PSR 10 | document itself, and this document outlines those cases. 11 | 12 | ## 1. Deprecation and Replacement 13 | 14 | If a PSR is found to require substantive updates or errata is no longer able to clarify confusion, 15 | then the PSR must be replaced, following the workflow set out in [workflow bylaw]. 16 | 17 | The original PSR may at some point in time be deprecated, as specified in the [votes bylaw]. 18 | 19 | Once a vote to deprecate a PSR and supersede it with another PSR has passed, the deprecated PSR must 20 | be marked as such in the original document and a link should be placed in the body. 21 | 22 | For example, the following Markdown be placed at the very top of the relevant standard file in the 23 | official PHP FIG GitHub repo `fig-standards`. 24 | 25 | > **Deprecated** - As of 2014-12-30 PSR-0 has been marked as deprecated. [PSR-4] is now recommended 26 | as an alternative. 27 | > [PSR-4]: http://php-fig.org/psr/psr-4 28 | 29 | ## 2. Dependencies 30 | 31 | As documents are expected to be replaced rather than amended, dependencies on 32 | other PSR's should be avoided whenever possible. For instance, the following is 33 | no longer permitted: 34 | 35 | > - Namespaces and classes MUST follow PSR-0. 36 | 37 | Instead - if a dependency is considered necessary by the working group creating it - then the following 38 | example can be used: 39 | 40 | > - Namespaces and classes MUST follow an autoloading PSR: [ [PSR-0] ]. 41 | 42 | The outer set of square brackets denote a "dependency list", which is a list of PSRs 43 | that are considered a compatible dependency. 44 | 45 | When more PSR's are added to the "dependency list" the same example would look like this: 46 | 47 | > - Namespaces and classes MUST follow an autoloading PSR: [ [PSR-0], [PSR-4] ]. 48 | 49 | New PSR's can be added to the "dependency list", but old PSR's can never be removed as this would break 50 | backwards compatibility. 51 | 52 | ## 3. Acceptable Amendments 53 | 54 | Other than updating the "dependency list", there are two other potentially acceptable amendment scenarios 55 | which do not require their own special vote. 56 | 57 | ### 3.1. Annotations 58 | 59 | If Errata is added which is deemed important enough by whoever is initiating the errata vote, 60 | annotations may be placed in or near the offending line so that readers know to view the errata for 61 | more information, with a link containing an anchor to that specific piece of errata. 62 | 63 | > - Something confusing about where brackets go. [cf. [errata](foo-meta.md#errata-1-foo)] 64 | 65 | This will be done as part of the errata vote, not its own. 66 | 67 | ### 3.2. Formatting & Typos 68 | 69 | If formatting is broken for any reason then changing formatting must not be considered a 70 | change to the document. These can be merged or pushed without hesitation by a secretary, as long as they 71 | don't change anything of any meaning or syntax. 72 | 73 | Some typos as trivial as a misplaced comma could have a subtle impact on meaning. Take special care not to 74 | alter backwards compatibility and create a vote if unsure. Common sense will help here. 75 | 76 | Examples: 77 | 78 | 1. HTML Tables are currently broken on php-fig.org because of the syntax used. 79 | 2. Somebody spelled something wrong and nobody spotted it for a year. 80 | 3. Problems with GitHub Markdown 81 | 82 | [workflow bylaw]: https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-workflow.md 83 | [votes bylaw]: https://github.com/php-fig/fig-standards/blob/master/bylaws/004-votes.md 84 | -------------------------------------------------------------------------------- /bylaws/008-psr-evolution.md: -------------------------------------------------------------------------------- 1 | # PSR evolution 2 | 3 | ## Scope and objectives 4 | 5 | A PSR is often comprised of text and code, generally interfaces. Those interfaces are pieces of code that are released and tagged at a specific moment in time. However, the PHP language doesn't stand still; it evolves over time. 6 | 7 | This means that those interfaces need to both provide a stable contract, as well as evolve to leverage new language features that could help better enforce the behaviors described in the PSR itself. 8 | 9 | At the same time, a PSR cannot be changed after its release (at which point only erratas are allowed), to protect a package that declared compatibility from becoming de facto incompatible. 10 | 11 | This document defines a process to be followed in updating PSR interfaces, in a way that is not breaking in regard to behavior for end users, and with an appropriate upgrade path for the consumers. 12 | 13 | ## Definitions 14 | 15 | * **Consumer** - libraries and projects that consume one or more interfaces from the code released as part of the PSR in question. 16 | * **Implementer** - libraries and projects that implement one or more interfaces from code released as part of the PSR in question. 17 | * **Cross-compatibility** - the ability for a consumer or an implementer to support more than one code version of the PSR with a single release of their own. 18 | 19 | ## New releases 20 | 21 | A new minor release of a PHP-FIG package containing interfaces for a PSR MUST follow these rules: 22 | * the new release MUST follow [Semantic Versioning](https://semver.org/) rules; 23 | * the PSR behavior MUST NOT be altered; 24 | * consumers or implementers of those interfaces MUST NOT suffer breaking changes; 25 | * the PHP version constraint of the PHP-FIG package MAY be increased to leverage newer language features, especially those that would aid cross-compatibility of consumers and implementers with the old and the new versions; 26 | * the PHP version constraint of the PHP-FIG package MUST NOT be altered to use newer language features that would create cross-compatibility issues. 27 | 28 | A new major release of a PHP-FIG package containing interfaces for a PSR MUST follow the same rules, with this exception: 29 | * the new major version of the package MAY contain breaking changes if the implementing packages have a reasonable upgrade path, like the possibility of releasing a cross-compatible implementation with the previous releases; 30 | * the new major version of the package MAY refer to a new, superseding PSR. 31 | 32 | Note that if the upgrade path causes the consumers or implementers to maintain multiple versions of their libraries side-by-side, only to support multiple versions of the same PSR, the upgrade path is to be considered too steep. 33 | 34 | ### Workflow 35 | 36 | Since releasing new versions of the interfaces MUST NOT alter the PSR in its behavior, those releases can be voted in with the same process as errata changes. The new releases MUST be declared and embedded with a brief explanation and a link in the PSR document, like in the following example: 37 | 38 | > \`\`\`php 39 | interface ContainerInterface 40 | { 41 | > // code snippet here 42 | } 43 | \`\`\` 44 | > 45 | > Since [psr/container version 1.1](https://packagist.org/packages/psr/container#1.1.0), the above interface has been updated to add argument type hints. 46 | 47 | In the example above, the last line is indicative of what should be added to the specification. 48 | 49 | The meta document MUST be amended with information detailing the consumer and/or implementer upgrade path. 50 | 51 | ### Practical example 52 | 53 | A common case for an upgrade in the interfaces is to add types for parameters and returns, since they are new language features introduced by PHP 7, and many PSR interfaces predate that release. We'll use a method from PSR-11 as an example of how a PSR interface could be updated. 54 | 55 | #### PSR-11: the interface 56 | 57 | PSR-11 is released with the [`psr/container` package](https://packagist.org/packages/psr/container) and it holds the `ContainerInterface`, which has this method: 58 | 59 | ```php 60 | /** 61 | * @param string $id Identifier of the entry to look for. 62 | * 63 | * @return bool 64 | */ 65 | public function has($id); 66 | ``` 67 | 68 | This method could be updated with a new minor release that adds the argument type for `$id`: 69 | 70 | ```php 71 | public function has(string $id); 72 | ``` 73 | 74 | This change would technically be a breaking change, but thanks to the [limited contravariance possible in PHP 7.2](https://wiki.php.net/rfc/parameter-no-type-variance), we can avoid that. This means that just by requiring `"php": "^7.2"` in the `psr/container` `composer.json`, we could tag this change as a minor release, and have all the consumers and implementers be automatically cross-compatible, provided that they declare `"psr/container": "^1.0"` (or equivalent) as a constraint. 75 | 76 | After this intermediate step, it would be possible to release a new major version, adding a return type hint: 77 | 78 | ```php 79 | public function has(string $id): bool; 80 | ``` 81 | 82 | This must be released as a new major version of `psr/container` (2.0); any package that would implement this would be able to declare `"psr/container": "^1.1 || ^2.0"`, since backward compatibility to the first release would be impossible, due to the sum of covariance and contravariance rules. 83 | 84 | #### PSR-11: the implementation 85 | 86 | On the other side, the implementers would be able to do a release cycle in the opposite fashion. The first release looks like this: 87 | 88 | ```php 89 | public function has($id); 90 | ``` 91 | 92 | The second release would add the return type, maintaining compatibility with the original interface: 93 | 94 | ```php 95 | public function has($id): bool; 96 | ``` 97 | 98 | A third release would also add the argument type hint: 99 | 100 | ```php 101 | public function has(string $id): bool; 102 | ``` 103 | -------------------------------------------------------------------------------- /bylaws/009-naming-conventions.md: -------------------------------------------------------------------------------- 1 | Naming conventions for code released by PHP FIG 2 | =============================================== 3 | 4 | 1. Interfaces MUST be suffixed by `Interface`: e.g. `Psr\Foo\BarInterface`. 5 | 2. Abstract classes MUST be prefixed by `Abstract`: e.g. `Psr\Foo\AbstractBar`. 6 | 3. Traits MUST be suffixed by `Trait`: e.g. `Psr\Foo\BarTrait`. 7 | 4. PSR-1, 4, and 12 MUST be followed. 8 | 5. For code released as part of a PSR, the vendor namespace MUST be `Psr` and the Composer package name MUST be `psr/` (e.g., `psr/log`). 9 | 6. For code released as part of a PER or any other Auxiliary Resources, the vendor namespace MUST be `Fig` and the Composer package name MUST be `fig/` (e.g., `fig/cache-util`). 10 | 7. There MUST be a package/second-level namespace in relation with the PSR or PER that covers the code. 11 | 8. Implementations of a given PSR or PER SHOULD declare a `provides` key in their `composer.json` file in the form `psr/-implementation` with a version number that matches the PSR being implemented. For example, `"psr/-implementation": "1.0.0"`. -------------------------------------------------------------------------------- /bylaws/100-implementation.md: -------------------------------------------------------------------------------- 1 | # Implementation of FIG 3.0 changes 2 | 3 | Upon the adoption of these bylaws: 4 | 5 | All currently sitting Secretaries will remain in their positions with no change in their term. 6 | 7 | The recognized Voting Representatives for member projects have 30 days to state their intent to remain member projects. If they do so, the Voting Representative will be recognized as the Project Representative going forward. No new admission vote is necessary. If the Voting Representative does not make any statement for 30 days, the project will be dropped from FIG membership. 8 | 9 | The Core Committee will be selected as though there were a 12-member vacancy according to the Vacancy rules above. The timetable of when this vote will occur will be announced by the Secretaries. 10 | 11 | All previously-approved PSRs will remain approved with no change, and will retain their current PSR number. 12 | 13 | The Editor of any PSR that is in Draft or Needs Review state will have a time limit from the time the Core Committee is seated to form an official Working Group, as defined in these bylaws. If a 5-member working group is formed then the PSR will automatically continue under these rules with no need for re-approval or re-entry. If the 5-member Working Group cannot be formed in that time then the PSR will automatically be listed as Abandoned. The exact timetable will be announced by the Secretaries. 14 | 15 | This bylaw (100) may be removed by the Secretaries when it is deemed no longer necessary to be kept and the transition to the new structure is complete. 16 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | # PHP Standard Recommendations 2 | 3 | According to the [PSR Workflow Bylaw][workflow] each PSR has a status as it is being worked on. Once a proposal has passed the Entrance Vote it will be listed here as "Draft". Unless a PSR is marked as "Accepted" it is subject to change. Draft can change drastically, but Review will only have minor changes. 4 | 5 | As also described in the [PSR Workflow Bylaw][workflow]. The Editor, or editors, of a proposal are the essentially the lead contributors and writers of the PSRs and they are supported by two voting members. Those voting members are the Coordinator who is responsible for managing the review stage and votes; and a second sponsor. 6 | 7 | ## Index by Status 8 | 9 | ### Accepted 10 | 11 | | Num | Title | Editor | Coordinator | Sponsor | 12 | |:---:|--------------------------------|--------------------------------|-------------------------|-------------------------| 13 | | 1 | [Basic Coding Standard][psr1] | Paul M. Jones | _N/A_ | _N/A_ | 14 | | 3 | [Logger Interface][psr3] | Jordi Boggiano | _N/A_ | _N/A_ | 15 | | 4 | [Autoloading Standard][psr4] | Paul M. Jones | Phil Sturgeon | Larry Garfield | 16 | | 6 | [Caching Interface][psr6] | Larry Garfield | Paul Dragoonis | Robert Hafner | 17 | | 7 | [HTTP Message Interface][psr7] | Matthew Weier O'Phinney | Beau Simensen | Paul M. Jones | 18 | | 11 | [Container Interface][psr11] | Matthieu Napoli, David Négrier | Matthew Weier O'Phinney | Korvin Szanto | 19 | | 12 | [Extended Coding Style Guide][psr12] | Korvin Szanto | Alexander Makarov | Chris Tankersley | 20 | | 13 | [Hypermedia Links][psr13] | Larry Garfield | Matthew Weier O'Phinney | Marc Alexander | 21 | | 14 | [Event Dispatcher][psr14] | Larry Garfield | _N/A_ | Cees-Jan Kiewiet | 22 | | 15 | [HTTP Handlers][psr15] | Woody Gilk | _N/A_ | Matthew Weier O'Phinney | 23 | | 16 | [Simple Cache][psr16] | Paul Dragoonis | Jordi Boggiano | Fabien Potencier | 24 | | 17 | [HTTP Factories][psr17] | Woody Gilk | _N/A_ | Matthew Weier O'Phinney | 25 | | 18 | [HTTP Client][psr18] | Tobias Nyholm | _N/A_ | Sara Golemon | 26 | 27 | ### Draft 28 | 29 | | Num | Title | Editor(s) | 30 | |:---:|--------------------------------------|--------------------------------| 31 | | 5 | [PHPDoc Standard][psr5] | Chuck Burgess | 32 | | 19 | [PHPDoc tags][psr19] | Chuck Burgess | 33 | | 20 | [Clock][psr20] | Chris Seufert | 34 | 35 | ### Abandoned 36 | 37 | | Num | Title | Editor(s) | 38 | |:---:|--------------------------------------|--------------------------------| 39 | | 8 | [Huggable Interface][psr8] | Larry Garfield | 40 | | 9 | [Security Advisories][psr9] | Michael Hess | 41 | | 10 | [Security Reporting Process][psr10] | Michael Hess | 42 | 43 | ### Deprecated 44 | 45 | | Num | Title | Editor | 46 | |:---:|--------------------------------|-------------------------| 47 | | 0 | [Autoloading Standard][psr0] | Matthew Weier O'Phinney | 48 | | 2 | [Coding Style Guide][psr2] | Paul M. Jones | 49 | 50 | ## Numerical Index 51 | 52 | | Num | Title | Editor(s) | Status | 53 | |:---:|--------------------------------------|--------------------------------|------------| 54 | | 0 | [Autoloading Standard][psr0] | Matthew Weier O'Phinney | Deprecated | 55 | | 1 | [Basic Coding Standard][psr1] | Paul M. Jones | Accepted | 56 | | 2 | [Coding Style Guide][psr2] | Paul M. Jones | Deprecated | 57 | | 3 | [Logger Interface][psr3] | Jordi Boggiano | Accepted | 58 | | 4 | [Autoloading Standard][psr4] | Paul M. Jones | Accepted | 59 | | 5 | [PHPDoc Standard][psr5] | Chuck Burgess | Draft | 60 | | 6 | [Caching Interface][psr6] | Larry Garfield | Accepted | 61 | | 7 | [HTTP Message Interface][psr7] | Matthew Weier O'Phinney | Accepted | 62 | | 8 | [Huggable Interface][psr8] | Larry Garfield | Abandoned | 63 | | 9 | [Security Advisories][psr9] | Michael Hess | Abandoned | 64 | | 10 | [Security Reporting Process][psr10] | Michael Hess | Abandoned | 65 | | 11 | [Container Interface][psr11] | Matthieu Napoli, David Négrier | Accepted | 66 | | 12 | [Extended Coding Style Guide][psr12] | Korvin Szanto | Accepted | 67 | | 13 | [Hypermedia Links][psr13] | Larry Garfield | Accepted | 68 | | 14 | [Event Dispatcher][psr14] | Larry Garfield | Accepted | 69 | | 15 | [HTTP Handlers][psr15] | Woody Gilk | Accepted | 70 | | 16 | [Simple Cache][psr16] | Paul Dragoonis | Accepted | 71 | | 17 | [HTTP Factories][psr17] | Woody Gilk | Accepted | 72 | | 18 | [HTTP Client][psr18] | Tobias Nyholm | Accepted | 73 | | 19 | [PHPDoc tags][psr19] | Chuck Burgess | Draft | 74 | | 20 | [Clock][psr20] | Chris Seufert | Draft | 75 | 76 | [workflow]: https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-workflow.md 77 | [psr0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 78 | [psr1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md 79 | [psr2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md 80 | [psr3]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md 81 | [psr4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-meta.md 82 | [psr5]: https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md 83 | [psr6]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-6-cache.md 84 | [psr7]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md 85 | [psr8]: https://github.com/php-fig/fig-standards/blob/master/proposed/psr-8-hug/ 86 | [psr9]: https://github.com/php-fig/fig-standards/blob/master/proposed/security-disclosure-publication.md 87 | [psr10]: https://github.com/php-fig/fig-standards/blob/master/proposed/security-reporting-process.md 88 | [psr11]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md 89 | [psr12]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-12-extended-coding-style-guide.md 90 | [psr13]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-13-links.md 91 | [psr14]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-14-event-dispatcher.md 92 | [psr15]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-15-request-handlers.md 93 | [psr16]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md 94 | [psr17]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-17-http-factory.md 95 | [psr18]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-18-http-client.md 96 | [psr19]: https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc-tags.md 97 | [psr20]: https://github.com/php-fig/fig-standards/blob/master/proposed/clock.md 98 | -------------------------------------------------------------------------------- /proposed/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phpDocumentor/fig-standards/4798bc539e92f362cda55a44e08475c269172352/proposed/.placeholder -------------------------------------------------------------------------------- /proposed/clock-meta.md: -------------------------------------------------------------------------------- 1 | # Clock Meta Document 2 | 3 | ## 1. Summary 4 | 5 | Getting the current time in applications is typically achieved using the `time()` or `microtime` functions, or by using a `new \DateTimeImmutable()` class. 6 | 7 | Due to the nature of time progression these methods cannot be used when predictable results are needed, such as during testing. 8 | 9 | This `ClockInterface` aims to provide a standard way to consume time that allows interoperability not only when consuming the "real" time but also when predictable results need to be available. This avoids the need to use PHP extensions for testing or redeclare the `time()` function in a local namespace. 10 | 11 | ## 2. Why Bother? 12 | 13 | There are currently a few libraries that provide this functionality, however there is no interopability between these different libraries, as they ship with their own clock interfaces. 14 | 15 | Symfony provides a package called `symfony/phpunit-bridge` that has a `Symfony\Bridge\PhpUnit\ClockMock` class, which allows mocking PHP's built-in time and date functions, however this does not solve mocking calls to `new \DateTimeImmutable()`. It also does not fully mock time when called from other libraries that rely on the system time. 16 | 17 | `Carbon\Carbon`, and its fork `Cake\Chronos\Chronos`, do provide mocking via a static `setTestNow()` method, but this provides no isolation and must be called again to stop mocking. 18 | 19 | Pros: 20 | 21 | * Consistent interface to get the current time; 22 | * Easy to mock the wall clock time for repeatablility. 23 | 24 | Cons: 25 | 26 | * Extra overhead and developer effort to get the current time, not as simple as 27 | calling `time()` or `date()`. 28 | 29 | ## 3. Scope 30 | 31 | ### 3.1 Goals 32 | 33 | * Provide a simple and mockable way to read the current time; 34 | * Allow interoperability between libraries when reading the clock. 35 | 36 | ### 3.2 Non-Goals 37 | 38 | * This PSR does not provide a recommendation on how and when to use the concepts 39 | described in this document, so it is not a coding standard; 40 | * This PSR does not provide a recommendation on how to handle timezones when 41 | retrieving the current time. This is left up to the implementation. 42 | * This PSR does not handle any scheduling methods like `sleep()` or `wait()` because such methods are not related to retrieving the current time. 43 | 44 | ## 4. Approaches 45 | 46 | ### 4.1 Chosen Approach 47 | 48 | We have decided to formalize the existing practices used by several other packages. Some popular packages providing this functionality are: 49 | 50 | * [`lcobucci/clock`](https://packagist.org/packages/lcobucci/clock) 51 | * [`kreait/clock`](https://packagist.org/packages/kreait/clock) 52 | * [`ergebnis/clock`](https://packagist.org/packages/ergebnis/clock) 53 | * [`mangoweb/clock`](https://packagist.org/packages/mangoweb/clock) 54 | 55 | (This list is not exhaustive!) 56 | 57 | Some of these provide interfaces and some rely on extending a clock class to mock the 58 | current time. 59 | 60 | These implementations all provide a `now()` method which returns a `DateTimeImmutable` object. As the `DateTimeImmutable` object allows retrieving the Unix timestamp, by calling `getTimestamp()` or `format('u.U')`, this interface does not define any special methods to retrieve a Unix timestamp or any other time information that is not available from a `DateTimeImmutable` object. 61 | 62 | ### 4.2 Timezones 63 | 64 | Time by now is defined by interaction of electromagnetic radiation with the excited states of certain atoms where the SI defines one second as the duration of 9192631770 cycles of radiation corresponding to the transition between two energy levels of the ground state of the caesium-133 atom at 0K. This means that retrieving the current time will always return the same time, no matter where it is observed. While the timezone defines *where* the time was observed it does not modify the actual "slice" of time. 65 | 66 | This means that for the sake of this PSR the timezone is considered an implementation detail of the interface. 67 | 68 | It is up to the implementation to make sure that the timezone is handled according to the business logic of the application. That is either by making sure that a call to `now()` will only return a `DateTimeImmutable` object with a known timezone (implicit contract) or by explicitly changing the timezone to be correct for the application. This can be done by calling `setTimezone()` to create a new `DateTimeImmutable` object with the given timezone. 69 | 70 | These actions are not defined in this interface. 71 | 72 | 73 | ### 4.2 Example Implementations 74 | 75 | ```php 76 | final class SystemClock implements \Psr\Clock\ClockInterface 77 | { 78 | public function now(): \DateTimeImmutable 79 | { 80 | return new \DateTimeImmutable(); 81 | } 82 | } 83 | 84 | final class FrozenClock implements \Psr\Clock\ClockInterface 85 | { 86 | private \DateTimeImmutable $now; 87 | 88 | public function __construct(\DateTimeImmutable $now) 89 | { 90 | $this->now = $now; 91 | } 92 | 93 | public function now(): \DateTimeImmutable 94 | { 95 | return clone $this->now; 96 | } 97 | } 98 | 99 | ``` 100 | 101 | ## 5. People 102 | 103 | ### 5.1 Editor 104 | 105 | * Chris Seufert 106 | 107 | ### 5.2 Sponsor 108 | 109 | * Chuck Burgess 110 | 111 | ### 5.3 Working group members 112 | 113 | * Luís Cobucci 114 | * Pol Dellaiera 115 | * Ben Edmunds 116 | * Jérôme Gamez 117 | * Andreas Heigl 118 | * Andreas Möller 119 | 120 | ## 6. Votes 121 | 122 | * [Entrance Vote](https://groups.google.com/g/php-fig/c/hIKqd0an-GI) 123 | 124 | ## 7. Relevant Links 125 | 126 | * https://github.com/ergebnis/clock/blob/main/src/Clock.php 127 | * https://github.com/icecave/chrono/blob/master/src/Clock/ClockInterface.php 128 | * https://github.com/Kdyby/DateTimeProvider/blob/master/src/DateTimeProviderInterface.php 129 | * https://github.com/kreait/clock-php/blob/main/src/Clock.php 130 | * https://github.com/lcobucci/clock/blob/2.1.x/src/Clock.php 131 | * https://github.com/mangoweb-backend/clock/blob/master/src/Clock.php 132 | * https://martinfowler.com/bliki/ClockWrapper.html 133 | 134 | ## 8. Past contributors 135 | 136 | This document stems from the work of many people in previous years, we recognize their effort: 137 | 138 | * 139 | _**Note:** Order descending chronologically._ 140 | -------------------------------------------------------------------------------- /proposed/clock.md: -------------------------------------------------------------------------------- 1 | Common Interface for Accessing the Clock 2 | ======================================== 3 | 4 | This document describes a simple interface for reading the system clock. 5 | 6 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 7 | "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 8 | interpreted as described in [RFC 2119][]. 9 | 10 | The final implementations MAY decorate the objects with more 11 | functionality than the one proposed but they MUST implement the indicated 12 | interfaces/functionality first. 13 | 14 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 15 | 16 | # 1. Specification 17 | 18 | ## 1.1 Introduction 19 | 20 | Creating a standard way of accessing the clock would allow interopability 21 | during testing, when testing behavior that has timing based side effects. 22 | Common ways to get the current time include calling `\time()` or 23 | `new DateTimeImmutable('now')`. However, this makes mocking the current time 24 | impossible in some situations. 25 | 26 | ## 1.2 Definitions 27 | 28 | * **Clock** - The clock is able to read the current time and date. 29 | 30 | * **Timestamp** - The current time as an integer number of seconds since 31 | Jan 1, 1970 00:00:00 UTC. 32 | 33 | ### 1.3 Usage 34 | 35 | There are some common usage patterns, which are outlined below: 36 | 37 | **Get the current timestamp** 38 | 39 | This should be done by using the `getTimestamp()` method on the returned `\DateTimeImmutable` like so: 40 | ```php 41 | $timestamp = $clock->now()->getTimestamp(); 42 | ``` 43 | 44 | # 2. Interfaces 45 | 46 | ## 2.1 ClockInterface 47 | 48 | The clock interface defines the most basic operation to read the current time and date from the clock. 49 | It MUST return the time as a `DateTimeImmutable`. 50 | 51 | ~~~php 52 | ``. 35 | 36 | Note that projects MAY choose to host their disclosure files on a domain 37 | other than their main project page. It is RECOMMENDED to not store the 38 | disclosures in a VCS as this can lead to the confusions about which branch 39 | is the relevant branch. If a VCS is used then additional steps SHOULD be taken 40 | to clearly document to users which branch contains all vulnerabilities for 41 | all versions. If necessary projects MAY however split vulnerability disclosure 42 | files by major version number. In this case again this SHOULD be clearly 43 | documented. 44 | 45 | ## Disclosure Format 46 | 47 | The disclosure format is based on Atom [1], which in turn is based on XML. It 48 | leverages the "The Common Vulnerability Reporting Framework (CVRF) v1.1" [2]. 49 | Specifically it leverages its dictionary [3] as its base terminology. 50 | 51 | **TODO**: Should we also provide a JSON serialization to lower the bar for projects. 52 | Aggregation services can then spring up to provide an Atom representation of 53 | these disclosures in JSON format. 54 | 55 | The Atom extensions [4] allow a structured description of the vulnerability to 56 | enable automated tools to determine if installed is likely affected by the 57 | vulnerability. However human readability is considered highly important and as 58 | such not the full CVRF is used. 59 | 60 | **TODO**: Review the Atom format and the supplied XSD 61 | 62 | Note that for each vulnerability only a single entry MUST be created. In case 63 | any information changes the original file MUST be updated along with the last 64 | update field. 65 | 66 | Any disclosure uses ``entryType`` using the following tags from the Atom 67 | namespace (required tags are labeled with "MUST"): 68 | 69 | * title (short description of the vulnerability and affected versions, MUST) 70 | * summary (description of the vulnerability) 71 | * author (contact information, MUST) 72 | * published (initial publication date, MUST) 73 | * updated (date of the last update) 74 | * link (to reference more information) 75 | * id (project specific vulnerability id) 76 | 77 | In addition the following tags are added: 78 | 79 | * reported (initial report date) 80 | * reportedBy (contact information for the persons or entity that initially reported the vulnerability) 81 | * resolvedBy (contact information for the persons or entity that resolved the vulnerability) 82 | * name (name of the product, MUST) 83 | * cve (unique CVE ID) 84 | * cwe (unique CWE ID) 85 | * severity (low, medium high) 86 | * affected (version(s) using composer syntax [5]) 87 | * status (open, in progress, disputed, completed, MUST) 88 | * remediation (textual description for how to fix an affected system) 89 | * remediationType (workaround, mitigation, vendor fix, none available, will not fix) 90 | * remediationLink (URL to give additional information for remediation) 91 | 92 | [1] https://tools.ietf.org/html/rfc4287 93 | [2] http://www.icasi.org/cvrf-1.1 94 | [3] http://www.icasi.org/cvrf-1.1-dictionary 95 | [4] security-disclosure-publication.xsd 96 | [5] https://getcomposer.org/doc/01-basic-usage.md#package-versions 97 | -------------------------------------------------------------------------------- /proposed/security-disclosure-publication.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | The PHP FIG security disclosure remediation construct is to be used to specify a specific remediation 45 | option for a specific vulnerability. 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /proposed/security-reporting-process-meta.md: -------------------------------------------------------------------------------- 1 | Security Disclosure Meta Document 2 | ================================= 3 | 4 | 1. Summary 5 | ---------- 6 | 7 | There are two aspects with dealing with security issues: One is the process 8 | by which security issues are reported and fixed in projects, the other 9 | is how the general public is informed about the issues and any remedies 10 | available. While PSR-10 addresses the later, this PSR, ie. PSR-9, deals with 11 | the former. So the goal of PSR-9 is to define the process by which security 12 | researchers and report security vulnerabilities to projects. It is important 13 | that when security vulnerabilities are found that researchers have an easy 14 | channel to the projects in question allowing them to disclose the issue to a 15 | controlled group of people. 16 | 17 | 2. Why Bother? 18 | -------------- 19 | 20 | As of right now, there isn't a common standard for most parts of this process. 21 | That is there isn't a standard where researchers can find out about the 22 | process for handling security issues for any given project. There is also 23 | no standard that explains to researchers what they can expect to happen if 24 | they report a vulnerability. More importantly there is no standard on which 25 | projects can base the security reporting process that best fits them. 26 | 27 | 3. Scope 28 | -------- 29 | 30 | ## 3.1 Goals 31 | 32 | * A defined process for how vulnerabilities are reported, the process by which 33 | these get fixed and finally disclosed to the public 34 | 35 | ## 3.2 Non-Goals 36 | 37 | * Methods for reducing security vulnerabilities 38 | * Publication of security issues and fixes (see PSR-10) 39 | 40 | 4. Approaches 41 | ------------- 42 | 43 | Currently the most viable approach seems to be defining a base line workflow 44 | for how security vulnerabilities go from discovery to fixing to public 45 | disclosure. Inspiration could be drawn from this list of security disclosure 46 | processes in various PHP and non-PHP projects: 47 | 48 | * https://symfony.com/security 49 | * https://framework.zend.com/security 50 | * https://www.yiiframework.com/security 51 | * https://www.drupal.org/security 52 | * https://codex.wordpress.org/FAQ_Security 53 | * https://www.sugarcrm.com/legal/security-policy 54 | * https://typo3.org/teams/security/ 55 | * https://book.cakephp.org/3.0/en/contributing/tickets.html#reporting-security-issues 56 | * https://www.concrete5.org/developers/security/ 57 | * https://developer.joomla.org/security.html 58 | * https://wiki.horde.org/SecurityManagement 59 | * https://www.revive-adserver.com/support/bugs/ 60 | * https://magento.com/security 61 | * https://www.apache.org/security/committers.html 62 | * https://www.mozilla.org/en-US/about/governance/policies/security-group/bugs/ 63 | * https://www.openbsd.org/security.html 64 | 65 | A summary of the differences and similarities can be found here: 66 | https://groups.google.com/d/msg/php-fig-psr-9-discussion/puGV_X0bj_M/Jr_IAS40StsJ 67 | 68 | 5. People 69 | --------- 70 | 71 | ### 5.1 Editor 72 | 73 | * Michael Hess 74 | 75 | ### 5.2 Sponsors 76 | 77 | * Larry Garfield (Drupal) 78 | * Korvin Szanto (concrete5) 79 | 80 | ### 5.3 Coordinator 81 | 82 | * Larry Garfield (Drupal) 83 | 84 | ### 5.4 Contributors 85 | 86 | * Lukas Kahwe Smith 87 | 88 | 6. Votes 89 | -------- 90 | 91 | 7. Relevant Links 92 | ----------------- 93 | -------------------------------------------------------------------------------- /proposed/security-reporting-process.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | There are two aspects with dealing with security issues: One is the process 4 | by which security issues are reported and fixed in projects, the other 5 | is how the general public is informed about the issues and any remedies 6 | available. While PSR-10 addresses the later, this PSR, ie. PSR-9, deals with 7 | the former. So the goal of PSR-9 is to define the process by which security 8 | researchers and report security vulnerabilities to projects. It is important 9 | that when security vulnerabilities are found that researchers have an easy 10 | channel to the projects in question allowing them to disclose the issue to a 11 | controlled group of people. 12 | 13 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 14 | "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 15 | interpreted as described in [RFC 2119][]. 16 | 17 | [RFC 2119]: http://tools.ietf.org/html/rfc2119 18 | 19 | ## Goal 20 | 21 | The goal of this PSR is to give researchers, project leads, upstream project 22 | leads and end users a defined and structured process for disclosing security 23 | vulnerabilities. 24 | 25 | ## Security Disclosure Process Discovery 26 | 27 | Every project MUST provide a link to its security disclosure process in 28 | an obvious place. Ideally this should be on the root page the main domain of 29 | the given project. This MAY be a sub-domain in case it is a sub-project of a 30 | larger initiative. The link MAY use the custom link relation 31 | ``php-vuln-reporting``, ie. for example 32 | ````. 33 | 34 | Projects SHOULD ideally make the location prominent itself 35 | by either creating a dedicated sub-domain like ``http://security.example.org`` 36 | or by making it a top level directory like ``http://example.org/security``. 37 | Alternatively projects MAY also simply reference this document, ie. PSR-9. 38 | By referencing PSR-9 a project basically states that they follow the 39 | default procedures as noted in the section "Default Procedures" towards 40 | the end of this document. Projects MUST list the variables noted at the start 41 | of that section in this reference (ie. project name, project domain, etc.). 42 | Projects MAY choose to list any part of the procedures that is not a MUST 43 | which they choose to omit. 44 | 45 | Note that projects MAY not have a dedicated domain. For example a project 46 | hosted on Github, Bitbucket or other service should still ensure that the 47 | process is referenced on the landing page, ie. for example 48 | http://github.com/example/somelib should ensure that the default branch 49 | has a README file which references the procedures used so that it is 50 | automatically displayed. 51 | 52 | If necessary projects MAY have different disclosure process 53 | for different major version number. In this case one URL MUST be provided 54 | for each major version. In the case a major version is no longer receiving 55 | security fixes, instead of an URL a project MAY opt to instead simply 56 | note that the version is no longer receiving security fixes. 57 | 58 | ## Security Disclosure Process 59 | 60 | Every project MUST provide an email address in their security disclosure 61 | process description as the ``contact email address``. Projects SHALL NOT 62 | use contact forms. 63 | 64 | **TODO**: Add more things found here https://groups.google.com/d/msg/php-fig-psr-9-discussion/puGV_X0bj_M/Jr_IAS40StsJ? 65 | 66 | ## Default Procedures 67 | 68 | * ``[project name]`` denotes the name on which the project uses to identify itself. 69 | * ``[project domain]`` denotes the main (sub)domain on which the project relies. 70 | 71 | If not specified otherwise, the ``contact email address`` is ``security@[project domain]``. 72 | 73 | **TODO**: Add more things noted in the previous section --------------------------------------------------------------------------------