├── .gitignore ├── LICENSE.txt ├── README.md ├── composer.json ├── composer.lock └── freemius ├── Exceptions ├── ArgumentNotExistException.php ├── EmptyArgumentException.php ├── Exception.php ├── InvalidArgumentException.php └── OAuthException.php ├── Freemius.php └── FreemiusBase.php /.gitignore: -------------------------------------------------------------------------------- 1 | .phpunit.result.cache 2 | .idea 3 | credentials.php 4 | vendor 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Freemius PHP SDK 2 | This SDK is a wrapper for accessing the API. It handles the endpoint's path and authorization signature generation. 3 | 4 | As a plugin or theme developer using Freemius, you can access your data via the `developer` scope or `plugin` scope. 5 | If you only need to access one product, we recommend using the `plugin` scope. You can get the product's credentials in *SETTINGS -> Keys*. 6 | If you need to access multiple products, use the `developer` scope. To get your credentials, click on *My Profile* at the top right menu and you'll find it in the *Keys* section. 7 | 8 | ```php 9 | define( 'FS__API_SCOPE', 'developer' ); 10 | define( 'FS__API_ENTITY_ID', 1234 ); 11 | define( 'FS__API_PUBLIC_KEY', 'pk_YOUR_PUBLIC_KEY' ); 12 | define( 'FS__API_SECRET_KEY', 'sk_YOUR_SECRET_KEY' ); 13 | 14 | // Init SDK. 15 | $api = new Freemius_Api(FS__API_SCOPE, FS__API_ENTITY_ID, FS__API_PUBLIC_KEY, FS__API_SECRET_KEY); 16 | 17 | // Get all products. 18 | $result = $api->Api('/plugins.json'); 19 | 20 | // Load 1st product data. 21 | $first_plugin_id = $result->plugins[0]->id; 22 | $first_plugin = $api->Api("/plugins/{$first_plugin_id}.json"); 23 | 24 | // Update title. 25 | $api->Api("/plugins/{$first_plugin_id}.json", 'PUT', array( 26 | 'title' => 'My New Title', 27 | )); 28 | ``` 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "freemius/php-sdk", 3 | "description": "Freemius PHP SDK", 4 | "keywords": ["freemius", "sdk", "php"], 5 | "homepage": "https://freemius.com", 6 | "license": "GPL-2.0+", 7 | "require": { 8 | "php": ">=5.2", 9 | "ext-curl": "*" 10 | }, 11 | "require-dev": { 12 | "phpunit/phpunit": "^9.6" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "9e2a6a60c85ae00c57cf93fbb5e7c5e9", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "doctrine/instantiator", 12 | "version": "1.5.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/instantiator.git", 16 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", 21 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^7.1 || ^8.0" 26 | }, 27 | "require-dev": { 28 | "doctrine/coding-standard": "^9 || ^11", 29 | "ext-pdo": "*", 30 | "ext-phar": "*", 31 | "phpbench/phpbench": "^0.16 || ^1", 32 | "phpstan/phpstan": "^1.4", 33 | "phpstan/phpstan-phpunit": "^1", 34 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", 35 | "vimeo/psalm": "^4.30 || ^5.4" 36 | }, 37 | "type": "library", 38 | "autoload": { 39 | "psr-4": { 40 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 41 | } 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "MIT" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Marco Pivetta", 50 | "email": "ocramius@gmail.com", 51 | "homepage": "https://ocramius.github.io/" 52 | } 53 | ], 54 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 55 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 56 | "keywords": [ 57 | "constructor", 58 | "instantiate" 59 | ], 60 | "support": { 61 | "issues": "https://github.com/doctrine/instantiator/issues", 62 | "source": "https://github.com/doctrine/instantiator/tree/1.5.0" 63 | }, 64 | "funding": [ 65 | { 66 | "url": "https://www.doctrine-project.org/sponsorship.html", 67 | "type": "custom" 68 | }, 69 | { 70 | "url": "https://www.patreon.com/phpdoctrine", 71 | "type": "patreon" 72 | }, 73 | { 74 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 75 | "type": "tidelift" 76 | } 77 | ], 78 | "time": "2022-12-30T00:15:36+00:00" 79 | }, 80 | { 81 | "name": "myclabs/deep-copy", 82 | "version": "1.12.0", 83 | "source": { 84 | "type": "git", 85 | "url": "https://github.com/myclabs/DeepCopy.git", 86 | "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" 87 | }, 88 | "dist": { 89 | "type": "zip", 90 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", 91 | "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", 92 | "shasum": "" 93 | }, 94 | "require": { 95 | "php": "^7.1 || ^8.0" 96 | }, 97 | "conflict": { 98 | "doctrine/collections": "<1.6.8", 99 | "doctrine/common": "<2.13.3 || >=3 <3.2.2" 100 | }, 101 | "require-dev": { 102 | "doctrine/collections": "^1.6.8", 103 | "doctrine/common": "^2.13.3 || ^3.2.2", 104 | "phpspec/prophecy": "^1.10", 105 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 106 | }, 107 | "type": "library", 108 | "autoload": { 109 | "files": [ 110 | "src/DeepCopy/deep_copy.php" 111 | ], 112 | "psr-4": { 113 | "DeepCopy\\": "src/DeepCopy/" 114 | } 115 | }, 116 | "notification-url": "https://packagist.org/downloads/", 117 | "license": [ 118 | "MIT" 119 | ], 120 | "description": "Create deep copies (clones) of your objects", 121 | "keywords": [ 122 | "clone", 123 | "copy", 124 | "duplicate", 125 | "object", 126 | "object graph" 127 | ], 128 | "support": { 129 | "issues": "https://github.com/myclabs/DeepCopy/issues", 130 | "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" 131 | }, 132 | "funding": [ 133 | { 134 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 135 | "type": "tidelift" 136 | } 137 | ], 138 | "time": "2024-06-12T14:39:25+00:00" 139 | }, 140 | { 141 | "name": "nikic/php-parser", 142 | "version": "v5.3.1", 143 | "source": { 144 | "type": "git", 145 | "url": "https://github.com/nikic/PHP-Parser.git", 146 | "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" 147 | }, 148 | "dist": { 149 | "type": "zip", 150 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", 151 | "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", 152 | "shasum": "" 153 | }, 154 | "require": { 155 | "ext-ctype": "*", 156 | "ext-json": "*", 157 | "ext-tokenizer": "*", 158 | "php": ">=7.4" 159 | }, 160 | "require-dev": { 161 | "ircmaxell/php-yacc": "^0.0.7", 162 | "phpunit/phpunit": "^9.0" 163 | }, 164 | "bin": [ 165 | "bin/php-parse" 166 | ], 167 | "type": "library", 168 | "extra": { 169 | "branch-alias": { 170 | "dev-master": "5.0-dev" 171 | } 172 | }, 173 | "autoload": { 174 | "psr-4": { 175 | "PhpParser\\": "lib/PhpParser" 176 | } 177 | }, 178 | "notification-url": "https://packagist.org/downloads/", 179 | "license": [ 180 | "BSD-3-Clause" 181 | ], 182 | "authors": [ 183 | { 184 | "name": "Nikita Popov" 185 | } 186 | ], 187 | "description": "A PHP parser written in PHP", 188 | "keywords": [ 189 | "parser", 190 | "php" 191 | ], 192 | "support": { 193 | "issues": "https://github.com/nikic/PHP-Parser/issues", 194 | "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" 195 | }, 196 | "time": "2024-10-08T18:51:32+00:00" 197 | }, 198 | { 199 | "name": "phar-io/manifest", 200 | "version": "2.0.4", 201 | "source": { 202 | "type": "git", 203 | "url": "https://github.com/phar-io/manifest.git", 204 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 205 | }, 206 | "dist": { 207 | "type": "zip", 208 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 209 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 210 | "shasum": "" 211 | }, 212 | "require": { 213 | "ext-dom": "*", 214 | "ext-libxml": "*", 215 | "ext-phar": "*", 216 | "ext-xmlwriter": "*", 217 | "phar-io/version": "^3.0.1", 218 | "php": "^7.2 || ^8.0" 219 | }, 220 | "type": "library", 221 | "extra": { 222 | "branch-alias": { 223 | "dev-master": "2.0.x-dev" 224 | } 225 | }, 226 | "autoload": { 227 | "classmap": [ 228 | "src/" 229 | ] 230 | }, 231 | "notification-url": "https://packagist.org/downloads/", 232 | "license": [ 233 | "BSD-3-Clause" 234 | ], 235 | "authors": [ 236 | { 237 | "name": "Arne Blankerts", 238 | "email": "arne@blankerts.de", 239 | "role": "Developer" 240 | }, 241 | { 242 | "name": "Sebastian Heuer", 243 | "email": "sebastian@phpeople.de", 244 | "role": "Developer" 245 | }, 246 | { 247 | "name": "Sebastian Bergmann", 248 | "email": "sebastian@phpunit.de", 249 | "role": "Developer" 250 | } 251 | ], 252 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 253 | "support": { 254 | "issues": "https://github.com/phar-io/manifest/issues", 255 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 256 | }, 257 | "funding": [ 258 | { 259 | "url": "https://github.com/theseer", 260 | "type": "github" 261 | } 262 | ], 263 | "time": "2024-03-03T12:33:53+00:00" 264 | }, 265 | { 266 | "name": "phar-io/version", 267 | "version": "3.2.1", 268 | "source": { 269 | "type": "git", 270 | "url": "https://github.com/phar-io/version.git", 271 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 272 | }, 273 | "dist": { 274 | "type": "zip", 275 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 276 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 277 | "shasum": "" 278 | }, 279 | "require": { 280 | "php": "^7.2 || ^8.0" 281 | }, 282 | "type": "library", 283 | "autoload": { 284 | "classmap": [ 285 | "src/" 286 | ] 287 | }, 288 | "notification-url": "https://packagist.org/downloads/", 289 | "license": [ 290 | "BSD-3-Clause" 291 | ], 292 | "authors": [ 293 | { 294 | "name": "Arne Blankerts", 295 | "email": "arne@blankerts.de", 296 | "role": "Developer" 297 | }, 298 | { 299 | "name": "Sebastian Heuer", 300 | "email": "sebastian@phpeople.de", 301 | "role": "Developer" 302 | }, 303 | { 304 | "name": "Sebastian Bergmann", 305 | "email": "sebastian@phpunit.de", 306 | "role": "Developer" 307 | } 308 | ], 309 | "description": "Library for handling version information and constraints", 310 | "support": { 311 | "issues": "https://github.com/phar-io/version/issues", 312 | "source": "https://github.com/phar-io/version/tree/3.2.1" 313 | }, 314 | "time": "2022-02-21T01:04:05+00:00" 315 | }, 316 | { 317 | "name": "phpunit/php-code-coverage", 318 | "version": "9.2.32", 319 | "source": { 320 | "type": "git", 321 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 322 | "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" 323 | }, 324 | "dist": { 325 | "type": "zip", 326 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", 327 | "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", 328 | "shasum": "" 329 | }, 330 | "require": { 331 | "ext-dom": "*", 332 | "ext-libxml": "*", 333 | "ext-xmlwriter": "*", 334 | "nikic/php-parser": "^4.19.1 || ^5.1.0", 335 | "php": ">=7.3", 336 | "phpunit/php-file-iterator": "^3.0.6", 337 | "phpunit/php-text-template": "^2.0.4", 338 | "sebastian/code-unit-reverse-lookup": "^2.0.3", 339 | "sebastian/complexity": "^2.0.3", 340 | "sebastian/environment": "^5.1.5", 341 | "sebastian/lines-of-code": "^1.0.4", 342 | "sebastian/version": "^3.0.2", 343 | "theseer/tokenizer": "^1.2.3" 344 | }, 345 | "require-dev": { 346 | "phpunit/phpunit": "^9.6" 347 | }, 348 | "suggest": { 349 | "ext-pcov": "PHP extension that provides line coverage", 350 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 351 | }, 352 | "type": "library", 353 | "extra": { 354 | "branch-alias": { 355 | "dev-main": "9.2.x-dev" 356 | } 357 | }, 358 | "autoload": { 359 | "classmap": [ 360 | "src/" 361 | ] 362 | }, 363 | "notification-url": "https://packagist.org/downloads/", 364 | "license": [ 365 | "BSD-3-Clause" 366 | ], 367 | "authors": [ 368 | { 369 | "name": "Sebastian Bergmann", 370 | "email": "sebastian@phpunit.de", 371 | "role": "lead" 372 | } 373 | ], 374 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 375 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 376 | "keywords": [ 377 | "coverage", 378 | "testing", 379 | "xunit" 380 | ], 381 | "support": { 382 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 383 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 384 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" 385 | }, 386 | "funding": [ 387 | { 388 | "url": "https://github.com/sebastianbergmann", 389 | "type": "github" 390 | } 391 | ], 392 | "time": "2024-08-22T04:23:01+00:00" 393 | }, 394 | { 395 | "name": "phpunit/php-file-iterator", 396 | "version": "3.0.6", 397 | "source": { 398 | "type": "git", 399 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 400 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 401 | }, 402 | "dist": { 403 | "type": "zip", 404 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 405 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 406 | "shasum": "" 407 | }, 408 | "require": { 409 | "php": ">=7.3" 410 | }, 411 | "require-dev": { 412 | "phpunit/phpunit": "^9.3" 413 | }, 414 | "type": "library", 415 | "extra": { 416 | "branch-alias": { 417 | "dev-master": "3.0-dev" 418 | } 419 | }, 420 | "autoload": { 421 | "classmap": [ 422 | "src/" 423 | ] 424 | }, 425 | "notification-url": "https://packagist.org/downloads/", 426 | "license": [ 427 | "BSD-3-Clause" 428 | ], 429 | "authors": [ 430 | { 431 | "name": "Sebastian Bergmann", 432 | "email": "sebastian@phpunit.de", 433 | "role": "lead" 434 | } 435 | ], 436 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 437 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 438 | "keywords": [ 439 | "filesystem", 440 | "iterator" 441 | ], 442 | "support": { 443 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 444 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" 445 | }, 446 | "funding": [ 447 | { 448 | "url": "https://github.com/sebastianbergmann", 449 | "type": "github" 450 | } 451 | ], 452 | "time": "2021-12-02T12:48:52+00:00" 453 | }, 454 | { 455 | "name": "phpunit/php-invoker", 456 | "version": "3.1.1", 457 | "source": { 458 | "type": "git", 459 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 460 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 461 | }, 462 | "dist": { 463 | "type": "zip", 464 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 465 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 466 | "shasum": "" 467 | }, 468 | "require": { 469 | "php": ">=7.3" 470 | }, 471 | "require-dev": { 472 | "ext-pcntl": "*", 473 | "phpunit/phpunit": "^9.3" 474 | }, 475 | "suggest": { 476 | "ext-pcntl": "*" 477 | }, 478 | "type": "library", 479 | "extra": { 480 | "branch-alias": { 481 | "dev-master": "3.1-dev" 482 | } 483 | }, 484 | "autoload": { 485 | "classmap": [ 486 | "src/" 487 | ] 488 | }, 489 | "notification-url": "https://packagist.org/downloads/", 490 | "license": [ 491 | "BSD-3-Clause" 492 | ], 493 | "authors": [ 494 | { 495 | "name": "Sebastian Bergmann", 496 | "email": "sebastian@phpunit.de", 497 | "role": "lead" 498 | } 499 | ], 500 | "description": "Invoke callables with a timeout", 501 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 502 | "keywords": [ 503 | "process" 504 | ], 505 | "support": { 506 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 507 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 508 | }, 509 | "funding": [ 510 | { 511 | "url": "https://github.com/sebastianbergmann", 512 | "type": "github" 513 | } 514 | ], 515 | "time": "2020-09-28T05:58:55+00:00" 516 | }, 517 | { 518 | "name": "phpunit/php-text-template", 519 | "version": "2.0.4", 520 | "source": { 521 | "type": "git", 522 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 523 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 524 | }, 525 | "dist": { 526 | "type": "zip", 527 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 528 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 529 | "shasum": "" 530 | }, 531 | "require": { 532 | "php": ">=7.3" 533 | }, 534 | "require-dev": { 535 | "phpunit/phpunit": "^9.3" 536 | }, 537 | "type": "library", 538 | "extra": { 539 | "branch-alias": { 540 | "dev-master": "2.0-dev" 541 | } 542 | }, 543 | "autoload": { 544 | "classmap": [ 545 | "src/" 546 | ] 547 | }, 548 | "notification-url": "https://packagist.org/downloads/", 549 | "license": [ 550 | "BSD-3-Clause" 551 | ], 552 | "authors": [ 553 | { 554 | "name": "Sebastian Bergmann", 555 | "email": "sebastian@phpunit.de", 556 | "role": "lead" 557 | } 558 | ], 559 | "description": "Simple template engine.", 560 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 561 | "keywords": [ 562 | "template" 563 | ], 564 | "support": { 565 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 566 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 567 | }, 568 | "funding": [ 569 | { 570 | "url": "https://github.com/sebastianbergmann", 571 | "type": "github" 572 | } 573 | ], 574 | "time": "2020-10-26T05:33:50+00:00" 575 | }, 576 | { 577 | "name": "phpunit/php-timer", 578 | "version": "5.0.3", 579 | "source": { 580 | "type": "git", 581 | "url": "https://github.com/sebastianbergmann/php-timer.git", 582 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 583 | }, 584 | "dist": { 585 | "type": "zip", 586 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 587 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 588 | "shasum": "" 589 | }, 590 | "require": { 591 | "php": ">=7.3" 592 | }, 593 | "require-dev": { 594 | "phpunit/phpunit": "^9.3" 595 | }, 596 | "type": "library", 597 | "extra": { 598 | "branch-alias": { 599 | "dev-master": "5.0-dev" 600 | } 601 | }, 602 | "autoload": { 603 | "classmap": [ 604 | "src/" 605 | ] 606 | }, 607 | "notification-url": "https://packagist.org/downloads/", 608 | "license": [ 609 | "BSD-3-Clause" 610 | ], 611 | "authors": [ 612 | { 613 | "name": "Sebastian Bergmann", 614 | "email": "sebastian@phpunit.de", 615 | "role": "lead" 616 | } 617 | ], 618 | "description": "Utility class for timing", 619 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 620 | "keywords": [ 621 | "timer" 622 | ], 623 | "support": { 624 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 625 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 626 | }, 627 | "funding": [ 628 | { 629 | "url": "https://github.com/sebastianbergmann", 630 | "type": "github" 631 | } 632 | ], 633 | "time": "2020-10-26T13:16:10+00:00" 634 | }, 635 | { 636 | "name": "phpunit/phpunit", 637 | "version": "9.6.21", 638 | "source": { 639 | "type": "git", 640 | "url": "https://github.com/sebastianbergmann/phpunit.git", 641 | "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" 642 | }, 643 | "dist": { 644 | "type": "zip", 645 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", 646 | "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", 647 | "shasum": "" 648 | }, 649 | "require": { 650 | "doctrine/instantiator": "^1.5.0 || ^2", 651 | "ext-dom": "*", 652 | "ext-json": "*", 653 | "ext-libxml": "*", 654 | "ext-mbstring": "*", 655 | "ext-xml": "*", 656 | "ext-xmlwriter": "*", 657 | "myclabs/deep-copy": "^1.12.0", 658 | "phar-io/manifest": "^2.0.4", 659 | "phar-io/version": "^3.2.1", 660 | "php": ">=7.3", 661 | "phpunit/php-code-coverage": "^9.2.32", 662 | "phpunit/php-file-iterator": "^3.0.6", 663 | "phpunit/php-invoker": "^3.1.1", 664 | "phpunit/php-text-template": "^2.0.4", 665 | "phpunit/php-timer": "^5.0.3", 666 | "sebastian/cli-parser": "^1.0.2", 667 | "sebastian/code-unit": "^1.0.8", 668 | "sebastian/comparator": "^4.0.8", 669 | "sebastian/diff": "^4.0.6", 670 | "sebastian/environment": "^5.1.5", 671 | "sebastian/exporter": "^4.0.6", 672 | "sebastian/global-state": "^5.0.7", 673 | "sebastian/object-enumerator": "^4.0.4", 674 | "sebastian/resource-operations": "^3.0.4", 675 | "sebastian/type": "^3.2.1", 676 | "sebastian/version": "^3.0.2" 677 | }, 678 | "suggest": { 679 | "ext-soap": "To be able to generate mocks based on WSDL files", 680 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 681 | }, 682 | "bin": [ 683 | "phpunit" 684 | ], 685 | "type": "library", 686 | "extra": { 687 | "branch-alias": { 688 | "dev-master": "9.6-dev" 689 | } 690 | }, 691 | "autoload": { 692 | "files": [ 693 | "src/Framework/Assert/Functions.php" 694 | ], 695 | "classmap": [ 696 | "src/" 697 | ] 698 | }, 699 | "notification-url": "https://packagist.org/downloads/", 700 | "license": [ 701 | "BSD-3-Clause" 702 | ], 703 | "authors": [ 704 | { 705 | "name": "Sebastian Bergmann", 706 | "email": "sebastian@phpunit.de", 707 | "role": "lead" 708 | } 709 | ], 710 | "description": "The PHP Unit Testing framework.", 711 | "homepage": "https://phpunit.de/", 712 | "keywords": [ 713 | "phpunit", 714 | "testing", 715 | "xunit" 716 | ], 717 | "support": { 718 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 719 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 720 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" 721 | }, 722 | "funding": [ 723 | { 724 | "url": "https://phpunit.de/sponsors.html", 725 | "type": "custom" 726 | }, 727 | { 728 | "url": "https://github.com/sebastianbergmann", 729 | "type": "github" 730 | }, 731 | { 732 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 733 | "type": "tidelift" 734 | } 735 | ], 736 | "time": "2024-09-19T10:50:18+00:00" 737 | }, 738 | { 739 | "name": "sebastian/cli-parser", 740 | "version": "1.0.2", 741 | "source": { 742 | "type": "git", 743 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 744 | "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" 745 | }, 746 | "dist": { 747 | "type": "zip", 748 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", 749 | "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", 750 | "shasum": "" 751 | }, 752 | "require": { 753 | "php": ">=7.3" 754 | }, 755 | "require-dev": { 756 | "phpunit/phpunit": "^9.3" 757 | }, 758 | "type": "library", 759 | "extra": { 760 | "branch-alias": { 761 | "dev-master": "1.0-dev" 762 | } 763 | }, 764 | "autoload": { 765 | "classmap": [ 766 | "src/" 767 | ] 768 | }, 769 | "notification-url": "https://packagist.org/downloads/", 770 | "license": [ 771 | "BSD-3-Clause" 772 | ], 773 | "authors": [ 774 | { 775 | "name": "Sebastian Bergmann", 776 | "email": "sebastian@phpunit.de", 777 | "role": "lead" 778 | } 779 | ], 780 | "description": "Library for parsing CLI options", 781 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 782 | "support": { 783 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 784 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" 785 | }, 786 | "funding": [ 787 | { 788 | "url": "https://github.com/sebastianbergmann", 789 | "type": "github" 790 | } 791 | ], 792 | "time": "2024-03-02T06:27:43+00:00" 793 | }, 794 | { 795 | "name": "sebastian/code-unit", 796 | "version": "1.0.8", 797 | "source": { 798 | "type": "git", 799 | "url": "https://github.com/sebastianbergmann/code-unit.git", 800 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 801 | }, 802 | "dist": { 803 | "type": "zip", 804 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 805 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 806 | "shasum": "" 807 | }, 808 | "require": { 809 | "php": ">=7.3" 810 | }, 811 | "require-dev": { 812 | "phpunit/phpunit": "^9.3" 813 | }, 814 | "type": "library", 815 | "extra": { 816 | "branch-alias": { 817 | "dev-master": "1.0-dev" 818 | } 819 | }, 820 | "autoload": { 821 | "classmap": [ 822 | "src/" 823 | ] 824 | }, 825 | "notification-url": "https://packagist.org/downloads/", 826 | "license": [ 827 | "BSD-3-Clause" 828 | ], 829 | "authors": [ 830 | { 831 | "name": "Sebastian Bergmann", 832 | "email": "sebastian@phpunit.de", 833 | "role": "lead" 834 | } 835 | ], 836 | "description": "Collection of value objects that represent the PHP code units", 837 | "homepage": "https://github.com/sebastianbergmann/code-unit", 838 | "support": { 839 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 840 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 841 | }, 842 | "funding": [ 843 | { 844 | "url": "https://github.com/sebastianbergmann", 845 | "type": "github" 846 | } 847 | ], 848 | "time": "2020-10-26T13:08:54+00:00" 849 | }, 850 | { 851 | "name": "sebastian/code-unit-reverse-lookup", 852 | "version": "2.0.3", 853 | "source": { 854 | "type": "git", 855 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 856 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 857 | }, 858 | "dist": { 859 | "type": "zip", 860 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 861 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 862 | "shasum": "" 863 | }, 864 | "require": { 865 | "php": ">=7.3" 866 | }, 867 | "require-dev": { 868 | "phpunit/phpunit": "^9.3" 869 | }, 870 | "type": "library", 871 | "extra": { 872 | "branch-alias": { 873 | "dev-master": "2.0-dev" 874 | } 875 | }, 876 | "autoload": { 877 | "classmap": [ 878 | "src/" 879 | ] 880 | }, 881 | "notification-url": "https://packagist.org/downloads/", 882 | "license": [ 883 | "BSD-3-Clause" 884 | ], 885 | "authors": [ 886 | { 887 | "name": "Sebastian Bergmann", 888 | "email": "sebastian@phpunit.de" 889 | } 890 | ], 891 | "description": "Looks up which function or method a line of code belongs to", 892 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 893 | "support": { 894 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 895 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 896 | }, 897 | "funding": [ 898 | { 899 | "url": "https://github.com/sebastianbergmann", 900 | "type": "github" 901 | } 902 | ], 903 | "time": "2020-09-28T05:30:19+00:00" 904 | }, 905 | { 906 | "name": "sebastian/comparator", 907 | "version": "4.0.8", 908 | "source": { 909 | "type": "git", 910 | "url": "https://github.com/sebastianbergmann/comparator.git", 911 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a" 912 | }, 913 | "dist": { 914 | "type": "zip", 915 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", 916 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a", 917 | "shasum": "" 918 | }, 919 | "require": { 920 | "php": ">=7.3", 921 | "sebastian/diff": "^4.0", 922 | "sebastian/exporter": "^4.0" 923 | }, 924 | "require-dev": { 925 | "phpunit/phpunit": "^9.3" 926 | }, 927 | "type": "library", 928 | "extra": { 929 | "branch-alias": { 930 | "dev-master": "4.0-dev" 931 | } 932 | }, 933 | "autoload": { 934 | "classmap": [ 935 | "src/" 936 | ] 937 | }, 938 | "notification-url": "https://packagist.org/downloads/", 939 | "license": [ 940 | "BSD-3-Clause" 941 | ], 942 | "authors": [ 943 | { 944 | "name": "Sebastian Bergmann", 945 | "email": "sebastian@phpunit.de" 946 | }, 947 | { 948 | "name": "Jeff Welch", 949 | "email": "whatthejeff@gmail.com" 950 | }, 951 | { 952 | "name": "Volker Dusch", 953 | "email": "github@wallbash.com" 954 | }, 955 | { 956 | "name": "Bernhard Schussek", 957 | "email": "bschussek@2bepublished.at" 958 | } 959 | ], 960 | "description": "Provides the functionality to compare PHP values for equality", 961 | "homepage": "https://github.com/sebastianbergmann/comparator", 962 | "keywords": [ 963 | "comparator", 964 | "compare", 965 | "equality" 966 | ], 967 | "support": { 968 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 969 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" 970 | }, 971 | "funding": [ 972 | { 973 | "url": "https://github.com/sebastianbergmann", 974 | "type": "github" 975 | } 976 | ], 977 | "time": "2022-09-14T12:41:17+00:00" 978 | }, 979 | { 980 | "name": "sebastian/complexity", 981 | "version": "2.0.3", 982 | "source": { 983 | "type": "git", 984 | "url": "https://github.com/sebastianbergmann/complexity.git", 985 | "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" 986 | }, 987 | "dist": { 988 | "type": "zip", 989 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", 990 | "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", 991 | "shasum": "" 992 | }, 993 | "require": { 994 | "nikic/php-parser": "^4.18 || ^5.0", 995 | "php": ">=7.3" 996 | }, 997 | "require-dev": { 998 | "phpunit/phpunit": "^9.3" 999 | }, 1000 | "type": "library", 1001 | "extra": { 1002 | "branch-alias": { 1003 | "dev-master": "2.0-dev" 1004 | } 1005 | }, 1006 | "autoload": { 1007 | "classmap": [ 1008 | "src/" 1009 | ] 1010 | }, 1011 | "notification-url": "https://packagist.org/downloads/", 1012 | "license": [ 1013 | "BSD-3-Clause" 1014 | ], 1015 | "authors": [ 1016 | { 1017 | "name": "Sebastian Bergmann", 1018 | "email": "sebastian@phpunit.de", 1019 | "role": "lead" 1020 | } 1021 | ], 1022 | "description": "Library for calculating the complexity of PHP code units", 1023 | "homepage": "https://github.com/sebastianbergmann/complexity", 1024 | "support": { 1025 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1026 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" 1027 | }, 1028 | "funding": [ 1029 | { 1030 | "url": "https://github.com/sebastianbergmann", 1031 | "type": "github" 1032 | } 1033 | ], 1034 | "time": "2023-12-22T06:19:30+00:00" 1035 | }, 1036 | { 1037 | "name": "sebastian/diff", 1038 | "version": "4.0.6", 1039 | "source": { 1040 | "type": "git", 1041 | "url": "https://github.com/sebastianbergmann/diff.git", 1042 | "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" 1043 | }, 1044 | "dist": { 1045 | "type": "zip", 1046 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", 1047 | "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", 1048 | "shasum": "" 1049 | }, 1050 | "require": { 1051 | "php": ">=7.3" 1052 | }, 1053 | "require-dev": { 1054 | "phpunit/phpunit": "^9.3", 1055 | "symfony/process": "^4.2 || ^5" 1056 | }, 1057 | "type": "library", 1058 | "extra": { 1059 | "branch-alias": { 1060 | "dev-master": "4.0-dev" 1061 | } 1062 | }, 1063 | "autoload": { 1064 | "classmap": [ 1065 | "src/" 1066 | ] 1067 | }, 1068 | "notification-url": "https://packagist.org/downloads/", 1069 | "license": [ 1070 | "BSD-3-Clause" 1071 | ], 1072 | "authors": [ 1073 | { 1074 | "name": "Sebastian Bergmann", 1075 | "email": "sebastian@phpunit.de" 1076 | }, 1077 | { 1078 | "name": "Kore Nordmann", 1079 | "email": "mail@kore-nordmann.de" 1080 | } 1081 | ], 1082 | "description": "Diff implementation", 1083 | "homepage": "https://github.com/sebastianbergmann/diff", 1084 | "keywords": [ 1085 | "diff", 1086 | "udiff", 1087 | "unidiff", 1088 | "unified diff" 1089 | ], 1090 | "support": { 1091 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1092 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" 1093 | }, 1094 | "funding": [ 1095 | { 1096 | "url": "https://github.com/sebastianbergmann", 1097 | "type": "github" 1098 | } 1099 | ], 1100 | "time": "2024-03-02T06:30:58+00:00" 1101 | }, 1102 | { 1103 | "name": "sebastian/environment", 1104 | "version": "5.1.5", 1105 | "source": { 1106 | "type": "git", 1107 | "url": "https://github.com/sebastianbergmann/environment.git", 1108 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" 1109 | }, 1110 | "dist": { 1111 | "type": "zip", 1112 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1113 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1114 | "shasum": "" 1115 | }, 1116 | "require": { 1117 | "php": ">=7.3" 1118 | }, 1119 | "require-dev": { 1120 | "phpunit/phpunit": "^9.3" 1121 | }, 1122 | "suggest": { 1123 | "ext-posix": "*" 1124 | }, 1125 | "type": "library", 1126 | "extra": { 1127 | "branch-alias": { 1128 | "dev-master": "5.1-dev" 1129 | } 1130 | }, 1131 | "autoload": { 1132 | "classmap": [ 1133 | "src/" 1134 | ] 1135 | }, 1136 | "notification-url": "https://packagist.org/downloads/", 1137 | "license": [ 1138 | "BSD-3-Clause" 1139 | ], 1140 | "authors": [ 1141 | { 1142 | "name": "Sebastian Bergmann", 1143 | "email": "sebastian@phpunit.de" 1144 | } 1145 | ], 1146 | "description": "Provides functionality to handle HHVM/PHP environments", 1147 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1148 | "keywords": [ 1149 | "Xdebug", 1150 | "environment", 1151 | "hhvm" 1152 | ], 1153 | "support": { 1154 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1155 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" 1156 | }, 1157 | "funding": [ 1158 | { 1159 | "url": "https://github.com/sebastianbergmann", 1160 | "type": "github" 1161 | } 1162 | ], 1163 | "time": "2023-02-03T06:03:51+00:00" 1164 | }, 1165 | { 1166 | "name": "sebastian/exporter", 1167 | "version": "4.0.6", 1168 | "source": { 1169 | "type": "git", 1170 | "url": "https://github.com/sebastianbergmann/exporter.git", 1171 | "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" 1172 | }, 1173 | "dist": { 1174 | "type": "zip", 1175 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", 1176 | "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", 1177 | "shasum": "" 1178 | }, 1179 | "require": { 1180 | "php": ">=7.3", 1181 | "sebastian/recursion-context": "^4.0" 1182 | }, 1183 | "require-dev": { 1184 | "ext-mbstring": "*", 1185 | "phpunit/phpunit": "^9.3" 1186 | }, 1187 | "type": "library", 1188 | "extra": { 1189 | "branch-alias": { 1190 | "dev-master": "4.0-dev" 1191 | } 1192 | }, 1193 | "autoload": { 1194 | "classmap": [ 1195 | "src/" 1196 | ] 1197 | }, 1198 | "notification-url": "https://packagist.org/downloads/", 1199 | "license": [ 1200 | "BSD-3-Clause" 1201 | ], 1202 | "authors": [ 1203 | { 1204 | "name": "Sebastian Bergmann", 1205 | "email": "sebastian@phpunit.de" 1206 | }, 1207 | { 1208 | "name": "Jeff Welch", 1209 | "email": "whatthejeff@gmail.com" 1210 | }, 1211 | { 1212 | "name": "Volker Dusch", 1213 | "email": "github@wallbash.com" 1214 | }, 1215 | { 1216 | "name": "Adam Harvey", 1217 | "email": "aharvey@php.net" 1218 | }, 1219 | { 1220 | "name": "Bernhard Schussek", 1221 | "email": "bschussek@gmail.com" 1222 | } 1223 | ], 1224 | "description": "Provides the functionality to export PHP variables for visualization", 1225 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1226 | "keywords": [ 1227 | "export", 1228 | "exporter" 1229 | ], 1230 | "support": { 1231 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1232 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" 1233 | }, 1234 | "funding": [ 1235 | { 1236 | "url": "https://github.com/sebastianbergmann", 1237 | "type": "github" 1238 | } 1239 | ], 1240 | "time": "2024-03-02T06:33:00+00:00" 1241 | }, 1242 | { 1243 | "name": "sebastian/global-state", 1244 | "version": "5.0.7", 1245 | "source": { 1246 | "type": "git", 1247 | "url": "https://github.com/sebastianbergmann/global-state.git", 1248 | "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" 1249 | }, 1250 | "dist": { 1251 | "type": "zip", 1252 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", 1253 | "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", 1254 | "shasum": "" 1255 | }, 1256 | "require": { 1257 | "php": ">=7.3", 1258 | "sebastian/object-reflector": "^2.0", 1259 | "sebastian/recursion-context": "^4.0" 1260 | }, 1261 | "require-dev": { 1262 | "ext-dom": "*", 1263 | "phpunit/phpunit": "^9.3" 1264 | }, 1265 | "suggest": { 1266 | "ext-uopz": "*" 1267 | }, 1268 | "type": "library", 1269 | "extra": { 1270 | "branch-alias": { 1271 | "dev-master": "5.0-dev" 1272 | } 1273 | }, 1274 | "autoload": { 1275 | "classmap": [ 1276 | "src/" 1277 | ] 1278 | }, 1279 | "notification-url": "https://packagist.org/downloads/", 1280 | "license": [ 1281 | "BSD-3-Clause" 1282 | ], 1283 | "authors": [ 1284 | { 1285 | "name": "Sebastian Bergmann", 1286 | "email": "sebastian@phpunit.de" 1287 | } 1288 | ], 1289 | "description": "Snapshotting of global state", 1290 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1291 | "keywords": [ 1292 | "global state" 1293 | ], 1294 | "support": { 1295 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1296 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" 1297 | }, 1298 | "funding": [ 1299 | { 1300 | "url": "https://github.com/sebastianbergmann", 1301 | "type": "github" 1302 | } 1303 | ], 1304 | "time": "2024-03-02T06:35:11+00:00" 1305 | }, 1306 | { 1307 | "name": "sebastian/lines-of-code", 1308 | "version": "1.0.4", 1309 | "source": { 1310 | "type": "git", 1311 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1312 | "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" 1313 | }, 1314 | "dist": { 1315 | "type": "zip", 1316 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", 1317 | "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", 1318 | "shasum": "" 1319 | }, 1320 | "require": { 1321 | "nikic/php-parser": "^4.18 || ^5.0", 1322 | "php": ">=7.3" 1323 | }, 1324 | "require-dev": { 1325 | "phpunit/phpunit": "^9.3" 1326 | }, 1327 | "type": "library", 1328 | "extra": { 1329 | "branch-alias": { 1330 | "dev-master": "1.0-dev" 1331 | } 1332 | }, 1333 | "autoload": { 1334 | "classmap": [ 1335 | "src/" 1336 | ] 1337 | }, 1338 | "notification-url": "https://packagist.org/downloads/", 1339 | "license": [ 1340 | "BSD-3-Clause" 1341 | ], 1342 | "authors": [ 1343 | { 1344 | "name": "Sebastian Bergmann", 1345 | "email": "sebastian@phpunit.de", 1346 | "role": "lead" 1347 | } 1348 | ], 1349 | "description": "Library for counting the lines of code in PHP source code", 1350 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1351 | "support": { 1352 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1353 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" 1354 | }, 1355 | "funding": [ 1356 | { 1357 | "url": "https://github.com/sebastianbergmann", 1358 | "type": "github" 1359 | } 1360 | ], 1361 | "time": "2023-12-22T06:20:34+00:00" 1362 | }, 1363 | { 1364 | "name": "sebastian/object-enumerator", 1365 | "version": "4.0.4", 1366 | "source": { 1367 | "type": "git", 1368 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1369 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 1370 | }, 1371 | "dist": { 1372 | "type": "zip", 1373 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 1374 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 1375 | "shasum": "" 1376 | }, 1377 | "require": { 1378 | "php": ">=7.3", 1379 | "sebastian/object-reflector": "^2.0", 1380 | "sebastian/recursion-context": "^4.0" 1381 | }, 1382 | "require-dev": { 1383 | "phpunit/phpunit": "^9.3" 1384 | }, 1385 | "type": "library", 1386 | "extra": { 1387 | "branch-alias": { 1388 | "dev-master": "4.0-dev" 1389 | } 1390 | }, 1391 | "autoload": { 1392 | "classmap": [ 1393 | "src/" 1394 | ] 1395 | }, 1396 | "notification-url": "https://packagist.org/downloads/", 1397 | "license": [ 1398 | "BSD-3-Clause" 1399 | ], 1400 | "authors": [ 1401 | { 1402 | "name": "Sebastian Bergmann", 1403 | "email": "sebastian@phpunit.de" 1404 | } 1405 | ], 1406 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1407 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1408 | "support": { 1409 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1410 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 1411 | }, 1412 | "funding": [ 1413 | { 1414 | "url": "https://github.com/sebastianbergmann", 1415 | "type": "github" 1416 | } 1417 | ], 1418 | "time": "2020-10-26T13:12:34+00:00" 1419 | }, 1420 | { 1421 | "name": "sebastian/object-reflector", 1422 | "version": "2.0.4", 1423 | "source": { 1424 | "type": "git", 1425 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1426 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 1427 | }, 1428 | "dist": { 1429 | "type": "zip", 1430 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1431 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1432 | "shasum": "" 1433 | }, 1434 | "require": { 1435 | "php": ">=7.3" 1436 | }, 1437 | "require-dev": { 1438 | "phpunit/phpunit": "^9.3" 1439 | }, 1440 | "type": "library", 1441 | "extra": { 1442 | "branch-alias": { 1443 | "dev-master": "2.0-dev" 1444 | } 1445 | }, 1446 | "autoload": { 1447 | "classmap": [ 1448 | "src/" 1449 | ] 1450 | }, 1451 | "notification-url": "https://packagist.org/downloads/", 1452 | "license": [ 1453 | "BSD-3-Clause" 1454 | ], 1455 | "authors": [ 1456 | { 1457 | "name": "Sebastian Bergmann", 1458 | "email": "sebastian@phpunit.de" 1459 | } 1460 | ], 1461 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1462 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1463 | "support": { 1464 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1465 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 1466 | }, 1467 | "funding": [ 1468 | { 1469 | "url": "https://github.com/sebastianbergmann", 1470 | "type": "github" 1471 | } 1472 | ], 1473 | "time": "2020-10-26T13:14:26+00:00" 1474 | }, 1475 | { 1476 | "name": "sebastian/recursion-context", 1477 | "version": "4.0.5", 1478 | "source": { 1479 | "type": "git", 1480 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1481 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" 1482 | }, 1483 | "dist": { 1484 | "type": "zip", 1485 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 1486 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 1487 | "shasum": "" 1488 | }, 1489 | "require": { 1490 | "php": ">=7.3" 1491 | }, 1492 | "require-dev": { 1493 | "phpunit/phpunit": "^9.3" 1494 | }, 1495 | "type": "library", 1496 | "extra": { 1497 | "branch-alias": { 1498 | "dev-master": "4.0-dev" 1499 | } 1500 | }, 1501 | "autoload": { 1502 | "classmap": [ 1503 | "src/" 1504 | ] 1505 | }, 1506 | "notification-url": "https://packagist.org/downloads/", 1507 | "license": [ 1508 | "BSD-3-Clause" 1509 | ], 1510 | "authors": [ 1511 | { 1512 | "name": "Sebastian Bergmann", 1513 | "email": "sebastian@phpunit.de" 1514 | }, 1515 | { 1516 | "name": "Jeff Welch", 1517 | "email": "whatthejeff@gmail.com" 1518 | }, 1519 | { 1520 | "name": "Adam Harvey", 1521 | "email": "aharvey@php.net" 1522 | } 1523 | ], 1524 | "description": "Provides functionality to recursively process PHP variables", 1525 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 1526 | "support": { 1527 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1528 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" 1529 | }, 1530 | "funding": [ 1531 | { 1532 | "url": "https://github.com/sebastianbergmann", 1533 | "type": "github" 1534 | } 1535 | ], 1536 | "time": "2023-02-03T06:07:39+00:00" 1537 | }, 1538 | { 1539 | "name": "sebastian/resource-operations", 1540 | "version": "3.0.4", 1541 | "source": { 1542 | "type": "git", 1543 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1544 | "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" 1545 | }, 1546 | "dist": { 1547 | "type": "zip", 1548 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", 1549 | "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", 1550 | "shasum": "" 1551 | }, 1552 | "require": { 1553 | "php": ">=7.3" 1554 | }, 1555 | "require-dev": { 1556 | "phpunit/phpunit": "^9.0" 1557 | }, 1558 | "type": "library", 1559 | "extra": { 1560 | "branch-alias": { 1561 | "dev-main": "3.0-dev" 1562 | } 1563 | }, 1564 | "autoload": { 1565 | "classmap": [ 1566 | "src/" 1567 | ] 1568 | }, 1569 | "notification-url": "https://packagist.org/downloads/", 1570 | "license": [ 1571 | "BSD-3-Clause" 1572 | ], 1573 | "authors": [ 1574 | { 1575 | "name": "Sebastian Bergmann", 1576 | "email": "sebastian@phpunit.de" 1577 | } 1578 | ], 1579 | "description": "Provides a list of PHP built-in functions that operate on resources", 1580 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1581 | "support": { 1582 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" 1583 | }, 1584 | "funding": [ 1585 | { 1586 | "url": "https://github.com/sebastianbergmann", 1587 | "type": "github" 1588 | } 1589 | ], 1590 | "time": "2024-03-14T16:00:52+00:00" 1591 | }, 1592 | { 1593 | "name": "sebastian/type", 1594 | "version": "3.2.1", 1595 | "source": { 1596 | "type": "git", 1597 | "url": "https://github.com/sebastianbergmann/type.git", 1598 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" 1599 | }, 1600 | "dist": { 1601 | "type": "zip", 1602 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 1603 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 1604 | "shasum": "" 1605 | }, 1606 | "require": { 1607 | "php": ">=7.3" 1608 | }, 1609 | "require-dev": { 1610 | "phpunit/phpunit": "^9.5" 1611 | }, 1612 | "type": "library", 1613 | "extra": { 1614 | "branch-alias": { 1615 | "dev-master": "3.2-dev" 1616 | } 1617 | }, 1618 | "autoload": { 1619 | "classmap": [ 1620 | "src/" 1621 | ] 1622 | }, 1623 | "notification-url": "https://packagist.org/downloads/", 1624 | "license": [ 1625 | "BSD-3-Clause" 1626 | ], 1627 | "authors": [ 1628 | { 1629 | "name": "Sebastian Bergmann", 1630 | "email": "sebastian@phpunit.de", 1631 | "role": "lead" 1632 | } 1633 | ], 1634 | "description": "Collection of value objects that represent the types of the PHP type system", 1635 | "homepage": "https://github.com/sebastianbergmann/type", 1636 | "support": { 1637 | "issues": "https://github.com/sebastianbergmann/type/issues", 1638 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" 1639 | }, 1640 | "funding": [ 1641 | { 1642 | "url": "https://github.com/sebastianbergmann", 1643 | "type": "github" 1644 | } 1645 | ], 1646 | "time": "2023-02-03T06:13:03+00:00" 1647 | }, 1648 | { 1649 | "name": "sebastian/version", 1650 | "version": "3.0.2", 1651 | "source": { 1652 | "type": "git", 1653 | "url": "https://github.com/sebastianbergmann/version.git", 1654 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 1655 | }, 1656 | "dist": { 1657 | "type": "zip", 1658 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 1659 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 1660 | "shasum": "" 1661 | }, 1662 | "require": { 1663 | "php": ">=7.3" 1664 | }, 1665 | "type": "library", 1666 | "extra": { 1667 | "branch-alias": { 1668 | "dev-master": "3.0-dev" 1669 | } 1670 | }, 1671 | "autoload": { 1672 | "classmap": [ 1673 | "src/" 1674 | ] 1675 | }, 1676 | "notification-url": "https://packagist.org/downloads/", 1677 | "license": [ 1678 | "BSD-3-Clause" 1679 | ], 1680 | "authors": [ 1681 | { 1682 | "name": "Sebastian Bergmann", 1683 | "email": "sebastian@phpunit.de", 1684 | "role": "lead" 1685 | } 1686 | ], 1687 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1688 | "homepage": "https://github.com/sebastianbergmann/version", 1689 | "support": { 1690 | "issues": "https://github.com/sebastianbergmann/version/issues", 1691 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 1692 | }, 1693 | "funding": [ 1694 | { 1695 | "url": "https://github.com/sebastianbergmann", 1696 | "type": "github" 1697 | } 1698 | ], 1699 | "time": "2020-09-28T06:39:44+00:00" 1700 | }, 1701 | { 1702 | "name": "theseer/tokenizer", 1703 | "version": "1.2.3", 1704 | "source": { 1705 | "type": "git", 1706 | "url": "https://github.com/theseer/tokenizer.git", 1707 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 1708 | }, 1709 | "dist": { 1710 | "type": "zip", 1711 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 1712 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 1713 | "shasum": "" 1714 | }, 1715 | "require": { 1716 | "ext-dom": "*", 1717 | "ext-tokenizer": "*", 1718 | "ext-xmlwriter": "*", 1719 | "php": "^7.2 || ^8.0" 1720 | }, 1721 | "type": "library", 1722 | "autoload": { 1723 | "classmap": [ 1724 | "src/" 1725 | ] 1726 | }, 1727 | "notification-url": "https://packagist.org/downloads/", 1728 | "license": [ 1729 | "BSD-3-Clause" 1730 | ], 1731 | "authors": [ 1732 | { 1733 | "name": "Arne Blankerts", 1734 | "email": "arne@blankerts.de", 1735 | "role": "Developer" 1736 | } 1737 | ], 1738 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1739 | "support": { 1740 | "issues": "https://github.com/theseer/tokenizer/issues", 1741 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 1742 | }, 1743 | "funding": [ 1744 | { 1745 | "url": "https://github.com/theseer", 1746 | "type": "github" 1747 | } 1748 | ], 1749 | "time": "2024-03-03T12:36:25+00:00" 1750 | } 1751 | ], 1752 | "aliases": [], 1753 | "minimum-stability": "stable", 1754 | "stability-flags": [], 1755 | "prefer-stable": false, 1756 | "prefer-lowest": false, 1757 | "platform": { 1758 | "php": ">=5.2", 1759 | "ext-curl": "*" 1760 | }, 1761 | "platform-dev": [], 1762 | "plugin-api-version": "2.3.0" 1763 | } 1764 | -------------------------------------------------------------------------------- /freemius/Exceptions/ArgumentNotExistException.php: -------------------------------------------------------------------------------- 1 | _result = $result; 20 | 21 | $code = 0; 22 | $message = 'Unknown error, please check GetResult().'; 23 | $type = ''; 24 | 25 | if (isset($result['error']) && is_array($result['error'])) 26 | { 27 | if (isset($result['error']['code'])) 28 | $code = $result['error']['code']; 29 | if (isset($result['error']['message'])) 30 | $message = $result['error']['message']; 31 | if (isset($result['error']['type'])) 32 | $type = $result['error']['type']; 33 | } 34 | 35 | $this->_type = $type; 36 | $this->_code = $code; 37 | 38 | parent::__construct($message, is_numeric($code) ? $code : 0); 39 | } 40 | 41 | /** 42 | * Return the associated result object returned by the API server. 43 | * 44 | * @return array The result from the API server 45 | */ 46 | public function getResult() 47 | { 48 | return $this->_result; 49 | } 50 | 51 | public function getStringCode() 52 | { 53 | return $this->_code; 54 | } 55 | 56 | public function getType() 57 | { 58 | return $this->_type; 59 | } 60 | 61 | /** 62 | * To make debugging easier. 63 | * 64 | * @return string The string representation of the error 65 | */ 66 | public function __toString() 67 | { 68 | $str = $this->getType() . ': '; 69 | 70 | if ($this->code != 0) 71 | $str .= $this->getStringCode() . ': '; 72 | 73 | return $str . $this->getMessage(); 74 | } 75 | } -------------------------------------------------------------------------------- /freemius/Exceptions/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | =') ? 'https' : 'http'); 28 | 29 | if ( ! defined('FS_API__ADDRESS')) 30 | define('FS_API__ADDRESS', FS_API__PROTOCOL . '://api.freemius.com'); 31 | if ( ! defined('FS_API__SANDBOX_ADDRESS')) 32 | define('FS_API__SANDBOX_ADDRESS', FS_API__PROTOCOL . '://sandbox-api.freemius.com'); 33 | 34 | if ( ! class_exists( 'Freemius_Api' ) ) { 35 | class Freemius_Api extends Freemius_Api_Base 36 | { 37 | /** 38 | * Default options for curl. 39 | */ 40 | public static $CURL_OPTS = array( 41 | CURLOPT_CONNECTTIMEOUT => 10, 42 | CURLOPT_RETURNTRANSFER => true, 43 | CURLOPT_TIMEOUT => 60, 44 | CURLOPT_USERAGENT => FS_SDK__USER_AGENT, 45 | CURLOPT_HTTPHEADER => array() 46 | ); 47 | 48 | /** 49 | * @param string $pScope 'app', 'developer', 'user' or 'install'. 50 | * @param number $pID Element's id. 51 | * @param string $pPublic Public key. 52 | * @param string|bool $pSecret Element's secret key. 53 | * @param bool $pSandbox Whether or not to run API in sandbox mode. 54 | */ 55 | public function __construct($pScope, $pID, $pPublic, $pSecret = false, $pSandbox = false) 56 | { 57 | // If secret key not provided, user public key encryption. 58 | if (is_bool($pSecret)) 59 | $pSecret = $pPublic; 60 | 61 | parent::Init($pScope, $pID, $pPublic, $pSecret, $pSandbox); 62 | } 63 | 64 | public function GetUrl($pCanonizedPath = '') 65 | { 66 | return ($this->_sandbox ? FS_API__SANDBOX_ADDRESS : FS_API__ADDRESS) . $pCanonizedPath; 67 | } 68 | 69 | /** 70 | * @var int Clock diff in seconds between current server to API server. 71 | */ 72 | private static $_clock_diff = 0; 73 | 74 | /** 75 | * Set clock diff for all API calls. 76 | * 77 | * @since 1.0.3 78 | * @param $pSeconds 79 | */ 80 | public static function SetClockDiff($pSeconds) 81 | { 82 | self::$_clock_diff = $pSeconds; 83 | } 84 | 85 | /** 86 | * Sign request with the following HTTP headers: 87 | * Content-MD5: MD5(HTTP Request body) 88 | * Date: Current date (i.e Sat, 14 Feb 2015 20:24:46 +0000) 89 | * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign, {scope_entity_secret_key})) 90 | * 91 | * @param string $pResourceUrl 92 | * @param string $pMethod 93 | * @param array $opts 94 | * @param string $pJsonEncodedParams 95 | * @param string $pContentType 96 | */ 97 | protected function SignRequest($pResourceUrl, $pMethod, &$opts, $pJsonEncodedParams, $pContentType) 98 | { 99 | $auth = $this->GenerateAuthorizationParams( 100 | $pResourceUrl, 101 | $pMethod, 102 | $pJsonEncodedParams, 103 | $pContentType 104 | ); 105 | 106 | $opts[CURLOPT_HTTPHEADER][] = ('Date: ' . $auth['date']); 107 | 108 | // Add authorization header. 109 | $opts[CURLOPT_HTTPHEADER][] = ('Authorization: ' . $auth['authorization']); 110 | 111 | if ( ! empty($auth['content_md5'])) 112 | $opts[CURLOPT_HTTPHEADER][] = ('Content-MD5: ' . $auth['content_md5']); 113 | } 114 | 115 | /** 116 | * @param string $pResourceUrl 117 | * @param string $pMethod 118 | * @param string $pJsonEncodedParams 119 | * @param string $pContentType 120 | * 121 | * @return array 122 | */ 123 | private function GenerateAuthorizationParams( 124 | $pResourceUrl, 125 | $pMethod = 'GET', 126 | $pJsonEncodedParams = '', 127 | $pContentType = '' 128 | ) 129 | { 130 | $pMethod = strtoupper($pMethod); 131 | 132 | $eol = "\n"; 133 | $content_md5 = ''; 134 | $now = (time() - self::$_clock_diff); 135 | $date = date('r', $now); 136 | 137 | if (in_array($pMethod, array('POST', 'PUT')) && ! empty($pJsonEncodedParams)) 138 | $content_md5 = md5($pJsonEncodedParams); 139 | 140 | $string_to_sign = implode($eol, array( 141 | $pMethod, 142 | $content_md5, 143 | $pContentType, 144 | $date, 145 | $pResourceUrl 146 | )); 147 | 148 | // If secret and public keys are identical, it means that 149 | // the signature uses public key hash encoding. 150 | $auth_type = ($this->_secret !== $this->_public) ? 'FS' : 'FSP'; 151 | 152 | $auth = array( 153 | 'date' => $date, 154 | 'authorization' => $auth_type . ' ' . $this->_id . ':' . 155 | $this->_public . ':' . 156 | self::Base64UrlEncode(hash_hmac( 157 | 'sha256', $string_to_sign, $this->_secret 158 | )) 159 | ); 160 | 161 | if ( ! empty($content_md5)) 162 | $auth['content_md5'] = $content_md5; 163 | 164 | return $auth; 165 | } 166 | 167 | /** 168 | * @param string $pPath 169 | * 170 | * @return string 171 | */ 172 | function GetSignedUrl($pPath) 173 | { 174 | $resource = explode('?', $this->CanonizePath($pPath)); 175 | $pResourceUrl = $resource[0]; 176 | 177 | $auth = $this->GenerateAuthorizationParams($pResourceUrl); 178 | 179 | return $this->GetUrl( 180 | $pResourceUrl . '?' . 181 | (1 < count($resource) && ! empty($resource[1]) ? $resource[1] . '&' : '') . 182 | http_build_query(array( 183 | 'auth_date' => $auth['date'], 184 | 'authorization' => $auth['authorization'] 185 | ))); 186 | } 187 | 188 | /** 189 | * Makes an HTTP request. This method can be overridden by subclasses if 190 | * developers want to do fancier things or use something other than curl to 191 | * make the request. 192 | * 193 | * @param $pCanonizedPath The URL to make the request to 194 | * @param string $pMethod HTTP method 195 | * @param array $pParams The parameters to use for the POST body 196 | * @param array $pFileParams 197 | * @param null $ch Initialized curl handle 198 | * 199 | * @return mixed 200 | * @throws Freemius_Exception 201 | */ 202 | public function MakeRequest($pCanonizedPath, $pMethod = 'GET', $pParams = array(), $pFileParams = array(), $ch = null) 203 | { 204 | if ( ! $ch) 205 | $ch = curl_init(); 206 | 207 | $opts = self::$CURL_OPTS; 208 | 209 | if ( ! is_array($opts[CURLOPT_HTTPHEADER])) 210 | $opts[CURLOPT_HTTPHEADER] = array(); 211 | 212 | $content_type = 'application/json'; 213 | $json_encoded_params = empty($pParams) ? 214 | '' : 215 | json_encode($pParams); 216 | 217 | $overidden_method = $pMethod; 218 | 219 | if ('POST' === $pMethod || 'PUT' === $pMethod) 220 | { 221 | if ( ! empty($pFileParams)) 222 | { 223 | $data = empty($json_encoded_params) ? 224 | '' : 225 | array('data' => $json_encoded_params); 226 | 227 | $json_encoded_params = ''; 228 | 229 | $boundary = ('----' . uniqid()); 230 | $post_fields = $this->GenerateMultipartBody($data, $pFileParams, $boundary); 231 | $content_type = "multipart/form-data; boundary={$boundary}"; 232 | 233 | if ('PUT' === $pMethod) 234 | { 235 | $query = parse_url($pCanonizedPath, PHP_URL_QUERY); 236 | $pCanonizedPath .= (is_string($query) ? '&' : '?') . 'method=PUT'; 237 | 238 | $overidden_method = $pMethod; 239 | $pMethod = 'POST'; 240 | } 241 | } 242 | else 243 | { 244 | $post_fields = $json_encoded_params; 245 | } 246 | 247 | if (is_array($pParams) && 0 < count($pParams)) 248 | { 249 | $opts[CURLOPT_POST] = count($pParams); 250 | $opts[CURLOPT_POSTFIELDS] = $post_fields; 251 | } 252 | 253 | $opts[CURLOPT_RETURNTRANSFER] = true; 254 | } 255 | else if ('GET' === $pMethod && ! empty($pParams)) 256 | { 257 | $pCanonizedPath = $this->AddQueryParams($pCanonizedPath, $pParams); 258 | } 259 | 260 | $opts[CURLOPT_HTTPHEADER][] = "Content-Type: $content_type"; 261 | 262 | $request_url = $this->GetUrl($pCanonizedPath); 263 | 264 | $opts[CURLOPT_URL] = $request_url; 265 | $opts[CURLOPT_CUSTOMREQUEST] = $pMethod; 266 | 267 | $resource = explode('?', $pCanonizedPath); 268 | $this->SignRequest($resource[0], $overidden_method, $opts, $json_encoded_params, $content_type); 269 | 270 | // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait 271 | // for 2 seconds if the server does not support this header. 272 | $opts[CURLOPT_HTTPHEADER][] = 'Expect:'; 273 | 274 | if ('https' === substr(strtolower($request_url), 0, 5)) 275 | { 276 | $opts[CURLOPT_SSL_VERIFYHOST] = false; 277 | $opts[CURLOPT_SSL_VERIFYPEER] = false; 278 | } 279 | 280 | curl_setopt_array($ch, $opts); 281 | $result = curl_exec($ch); 282 | 283 | /*if (curl_errno($ch) == 60) // CURLE_SSL_CACERT 284 | { 285 | self::errorLog('Invalid or no certificate authority found, using bundled information'); 286 | curl_setopt($ch, CURLOPT_CAINFO, 287 | dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); 288 | $result = curl_exec($ch); 289 | }*/ 290 | 291 | // With dual stacked DNS responses, it's possible for a server to 292 | // have IPv6 enabled but not have IPv6 connectivity. If this is 293 | // the case, curl will try IPv4 first and if that fails, then it will 294 | // fall back to IPv6 and the error EHOSTUNREACH is returned by the 295 | // operating system. 296 | if (false === $result && empty($opts[CURLOPT_IPRESOLVE])) 297 | { 298 | $matches = array(); 299 | $regex = '/Failed to connect to ([^:].*): Network is unreachable/'; 300 | if (preg_match($regex, curl_error($ch), $matches)) 301 | { 302 | if (strlen(@inet_pton($matches[1])) === 16) 303 | { 304 | self::errorLog('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.'); 305 | self::$CURL_OPTS[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; 306 | curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); 307 | $result = curl_exec($ch); 308 | } 309 | } 310 | } 311 | 312 | if ($result === false) 313 | { 314 | $e = new Freemius_Exception(array( 315 | 'error' => array( 316 | 'code' => curl_errno($ch), 317 | 'message' => curl_error($ch), 318 | 'type' => 'CurlException', 319 | ), 320 | )); 321 | 322 | curl_close($ch); 323 | throw $e; 324 | } 325 | 326 | curl_close($ch); 327 | 328 | return $result; 329 | } 330 | 331 | /** 332 | * @param array $pParams 333 | * @param array $pFileParams 334 | * @param string $pBoundary 335 | * 336 | * @return string 337 | */ 338 | private function GenerateMultipartBody($pParams, $pFileParams, $pBoundary) 339 | { 340 | $body = ''; 341 | 342 | if ( ! empty($pParams)) 343 | { 344 | foreach ($pParams as $name => $value) 345 | { 346 | $body = ('--' . $pBoundary . PHP_EOL) . 347 | ("Content-Disposition: form-data; name=\"{$name}\"" . PHP_EOL) . 348 | PHP_EOL . 349 | ($value . PHP_EOL); 350 | } 351 | } 352 | 353 | foreach ($pFileParams as $name => $file_path) 354 | { 355 | $filename = basename($file_path); 356 | 357 | $body .= 358 | ('--' . $pBoundary . PHP_EOL) . 359 | ("Content-Disposition: form-data; name=\"{$name}\"; filename=\"{$filename}\"" . PHP_EOL) . 360 | ('Content-Type: ' . $this->GetMimeContentType($file_path) . PHP_EOL) . 361 | PHP_EOL . 362 | (file_get_contents($file_path) . PHP_EOL); 363 | } 364 | 365 | $body .= ('--' . $pBoundary . '--'); 366 | 367 | return $body; 368 | } 369 | 370 | /** 371 | * @param string $pFilename 372 | * 373 | * @return string 374 | * 375 | * @throws Exception 376 | */ 377 | private function GetMimeContentType($pFilename) 378 | { 379 | if (function_exists('mime_content_type')) 380 | return mime_content_type($pFilename); 381 | 382 | $mime_types = array( 383 | 'zip' => 'application/zip', 384 | 'jpg' => 'image/jpeg', 385 | 'jpeg' => 'image/jpeg', 386 | 'png' => 'image/png', 387 | 'gif' => 'image/gif', 388 | ); 389 | 390 | $ext = explode('.', $pFilename)[1]; 391 | 392 | if ( ! isset($mime_types[$ext])) 393 | throw new Exception('Unknown file type'); 394 | 395 | return $mime_types[$ext]; 396 | } 397 | } 398 | } -------------------------------------------------------------------------------- /freemius/FreemiusBase.php: -------------------------------------------------------------------------------- 1 | _id = $pID; 68 | $this->_public = $pPublic; 69 | $this->_secret = $pSecret; 70 | $this->_scope = $pScope; 71 | $this->_sandbox = $pSandbox; 72 | } 73 | 74 | public function IsSandbox() 75 | { 76 | return $this->_sandbox; 77 | } 78 | 79 | function CanonizePath($pPath) 80 | { 81 | $pPath = trim($pPath, '/'); 82 | $query_pos = strpos($pPath, '?'); 83 | $query = ''; 84 | 85 | if (false !== $query_pos) { 86 | $query = substr($pPath, $query_pos); 87 | $pPath = substr($pPath, 0, $query_pos); 88 | } 89 | 90 | // Trim '.json' suffix. 91 | $format_length = strlen('.' . self::FORMAT); 92 | $start = $format_length * (-1); //negative 93 | if (substr(strtolower($pPath), $start) === ('.' . self::FORMAT)) 94 | $pPath = substr($pPath, 0, strlen($pPath) - $format_length); 95 | 96 | switch ($this->_scope) { 97 | case 'app': 98 | $base = '/apps/' . $this->_id; 99 | break; 100 | case 'developer': 101 | $base = '/developers/' . $this->_id; 102 | break; 103 | case 'store': 104 | $base = '/stores/' . $this->_id; 105 | break; 106 | case 'user': 107 | $base = '/users/' . $this->_id; 108 | break; 109 | case 'plugin': 110 | $base = '/plugins/' . $this->_id; 111 | break; 112 | case 'install': 113 | $base = '/installs/' . $this->_id; 114 | break; 115 | default: 116 | throw new Freemius_Exception('Scope not implemented.'); 117 | } 118 | 119 | return '/v' . FS_API__VERSION . $base . 120 | (!empty($pPath) ? '/' : '') . $pPath . 121 | ((false === strpos($pPath, '.')) ? '.' . self::FORMAT : '') . $query; 122 | } 123 | 124 | abstract function MakeRequest($pCanonizedPath, $pMethod = 'GET', $pParams = array(), $pFileParams = array()); 125 | 126 | private function _Api($pPath, $pMethod = 'GET', $pParams = array(), $pFileParams = array()) 127 | { 128 | $pMethod = strtoupper($pMethod); 129 | 130 | try { 131 | $result = $this->MakeRequest($pPath, $pMethod, $pParams, $pFileParams); 132 | } 133 | catch (Freemius_Exception $e) 134 | { 135 | // Map to error object. 136 | $result = json_encode($e->getResult()); 137 | } catch (Exception $e) { 138 | // Map to error object. 139 | $result = json_encode(array( 140 | 'error' => array( 141 | 'type' => 'Unknown', 142 | 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', 143 | 'code' => 'unknown', 144 | 'http' => 402 145 | ) 146 | )); 147 | } 148 | 149 | $decoded = json_decode($result); 150 | 151 | return (null === $decoded) ? $result : $decoded; 152 | } 153 | 154 | /** 155 | * @return bool True if successful connectivity to the API endpoint using ping.json endpoint. 156 | */ 157 | public function Test() 158 | { 159 | $pong = $this->_Api('/v' . FS_API__VERSION . '/ping.json'); 160 | 161 | return (is_object($pong) && isset($pong->api) && 'pong' === $pong->api); 162 | } 163 | 164 | /** 165 | * Find clock diff between current server to API server. 166 | * 167 | * @since 1.0.2 168 | * @return int Clock diff in seconds. 169 | */ 170 | public function FindClockDiff() 171 | { 172 | $time = time(); 173 | $pong = $this->_Api('/v' . FS_API__VERSION . '/ping.json'); 174 | return ($time - strtotime($pong->timestamp)); 175 | } 176 | 177 | /** 178 | * Add query parameters to the path. 179 | * 180 | * @param string $pPath Path. 181 | * @param array $pParams Query parameters. 182 | * 183 | * @return string Path with query parameters. 184 | */ 185 | protected function AddQueryParams($pPath, $pParams) 186 | { 187 | $query_string = http_build_query($pParams); 188 | 189 | return $pPath . (strpos($pPath, '?') === false ? '?' : '&') . $query_string; 190 | } 191 | 192 | public function Api($pPath, $pMethod = 'GET', $pParams = array(), $pFileParams = array()) 193 | { 194 | return $this->_Api($this->CanonizePath($pPath), $pMethod, $pParams, $pFileParams); 195 | } 196 | 197 | /** 198 | * Base64 encoding that does not need to be urlencode()ed. 199 | * Exactly the same as base64_encode except it uses 200 | * - instead of + 201 | * _ instead of / 202 | * No padded = 203 | * 204 | * @param string $input base64UrlEncoded string 205 | * @return string 206 | */ 207 | protected static function Base64UrlDecode($input) 208 | { 209 | return base64_decode(strtr($input, '-_', '+/')); 210 | } 211 | 212 | /** 213 | * Base64 encoding that does not need to be urlencode()ed. 214 | * Exactly the same as base64_encode except it uses 215 | * - instead of + 216 | * _ instead of / 217 | * 218 | * @param string $input string 219 | * @return string base64Url encoded string 220 | */ 221 | protected static function Base64UrlEncode($input) 222 | { 223 | $str = strtr(base64_encode($input), '+/', '-_'); 224 | $str = str_replace('=', '', $str); 225 | 226 | return $str; 227 | } 228 | 229 | } 230 | } --------------------------------------------------------------------------------