├── .gitignore
├── .styleci.yml
├── .travis.yml
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── docs
└── README.md
├── examples
├── edit_file.php
└── includes
│ ├── Example.php
│ └── cookies
│ ├── .gitignore
│ └── example.txt
├── phpunit.xml.dist
├── src
└── NetscapeCookieFileHandler
│ ├── Configuration
│ ├── Configuration.php
│ ├── ConfigurationInterface.php
│ ├── ConfigurationTrait.php
│ ├── HasConfigurationInterface.php
│ ├── HasMandatoryConfigurationInterface.php
│ └── MandatoryConfigurationTrait.php
│ ├── Cookie
│ ├── Cookie.php
│ ├── CookieCollection.php
│ ├── CookieCollectionInterface.php
│ ├── CookieInterface.php
│ └── Exception
│ │ └── CookieCollectionException.php
│ ├── CookieFileHandler.php
│ ├── CookieFileHandlerInterface.php
│ ├── Exception
│ └── NetscapeCookieFileHandlerException.php
│ ├── Jar
│ ├── CookieJar.php
│ ├── CookieJarInterface.php
│ └── Exception
│ │ └── CookieJarException.php
│ ├── Parser
│ ├── Exception
│ │ └── ParserException.php
│ ├── Parser.php
│ └── ParserInterface.php
│ └── Persister
│ ├── Exception
│ └── PersisterException.php
│ ├── Persister.php
│ └── PersisterInterface.php
└── tests
├── NetscapeCookieFileHandler
├── Configuration
│ └── ConfigurationTest.php
├── Cookie
│ ├── CookieCollectionTest.php
│ └── CookieTest.php
├── CookieFileHandlerTest.php
├── Jar
│ ├── CookieJarPersisterTest.php
│ └── CookieJarTest.php
├── Parser
│ └── ParserTest.php
└── _files
│ └── cookies
│ ├── .gitignore
│ ├── example.txt
│ └── example_expected.txt
└── bootstrap.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | build/
3 | tmp/*
4 | /phpunit.xml
5 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: psr2
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 7.0
5 | - nightly
6 |
7 | before_script:
8 | - composer self-update
9 | - composer install --prefer-source --no-interaction --dev
10 |
11 | script: phpunit
12 |
13 | matrix:
14 | allow_failures:
15 | - php: nightly
16 |
17 | sudo: false
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 | {one line to give the program's name and a brief idea of what it does.}
635 | Copyright (C) {year} {name of author}
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | {project} Copyright (C) {year} {fullname}
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Netscape Cookie File Handler
2 | [](https://travis-ci.org/kegi/netscape-cookie-file-handler)
3 | [](https://packagist.org/packages/kegi/netscape-cookie-file-handler)
4 | [](https://codeclimate.com/github/kegi/netscape-cookie-file-handler/coverage)
5 |
6 | [](https://codeclimate.com/github/kegi/netscape-cookie-file-handler)
7 | [](https://codeclimate.com/github/kegi/netscape-cookie-file-handler)
8 | [](https://insight.sensiolabs.com/projects/9ecd72f2-a463-4eca-9c55-4733d936753f)
9 |
10 | This library allows you to manipulate Netscape Cookie File (eg. Cookies generated by CURL).
11 |
12 | ----------
13 |
14 | ## Requirements
15 | This is library is only available for **PHP7+**
16 | There is no other dependencies
17 |
18 | ## Installation
19 | This library is available on packagist (**Composer**)
20 | ```shell
21 | composer require kegi/netscape-cookie-file-handler
22 | ```
23 |
24 | ## What are Cookies Files ?
25 | The Netscape cookie files are widely used. Curl, by example, allows you to select a file (called the cookie jar) to save and read the cookies using this format. This library will help you to manipulate and read those cookies.
26 |
27 | ## Example
28 | Simple example of reading + writing cookies
29 |
30 | ```php
31 | /*Open and parse the cookie file*/
32 |
33 | $configuration = (new Configuration())->setCookieDir('cookies/');
34 | $cookieJar = (new CookieFileHandler($configuration))->parseFile('my_cookie_file');
35 |
36 | /*Add (and save) a cookie*/
37 |
38 | $cookieJar->add(
39 | (new Cookie())
40 | ->setHttpOnly(true)
41 | ->setPath('/foo')
42 | ->setSecure(true)
43 | ->setExpire(new DateTime('2020-02-20 20:20:02'))
44 | ->setName('foo')
45 | ->setValue('bar')
46 | )->persist();
47 | ```
48 |
49 | ## Documentation
50 |
51 | Learn how to use the library here : [documentation](/docs/README.md).
52 |
53 | ## Contribution
54 |
55 | Feel free to contact me or send pull requests !
56 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kegi/netscape-cookie-file-handler",
3 | "type": "library",
4 | "description": "Netscape Cookie File Handler",
5 | "keywords": ["netscape", "cookie", "cookie file"],
6 | "license": "GPL-3.0",
7 | "authors": [
8 | {
9 | "name": "Kevin Gilbert",
10 | "email": "kevin@kegisiteweb.com"
11 | }
12 | ],
13 | "require": {
14 | "php": ">=7.0"
15 | },
16 | "require-dev": {
17 | "phpunit/phpunit": "^5.2",
18 | "codeclimate/php-test-reporter": "dev-master"
19 | },
20 | "autoload": {
21 | "psr-4": {
22 | "KeGi\\NetscapeCookieFileHandler\\": "src/NetscapeCookieFileHandler"
23 | }
24 | },
25 | "autoload-dev": {
26 | "psr-4": {
27 | "KeGi\\NetscapeCookieFileHandler\\Tests\\": ["tests/NetscapeCookieFileHandler"]
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/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": "1029769f450912f7454b7a81ebb2c16c",
8 | "packages": [],
9 | "packages-dev": [
10 | {
11 | "name": "codeclimate/php-test-reporter",
12 | "version": "dev-master",
13 | "source": {
14 | "type": "git",
15 | "url": "https://github.com/codeclimate/php-test-reporter.git",
16 | "reference": "02790d733f9eb43d0a5981962c41846092fb387f"
17 | },
18 | "dist": {
19 | "type": "zip",
20 | "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/02790d733f9eb43d0a5981962c41846092fb387f",
21 | "reference": "02790d733f9eb43d0a5981962c41846092fb387f",
22 | "shasum": ""
23 | },
24 | "require": {
25 | "ext-curl": "*",
26 | "php": ">=5.3",
27 | "satooshi/php-coveralls": "0.6.*",
28 | "symfony/console": ">=2.0"
29 | },
30 | "require-dev": {
31 | "ext-xdebug": "*",
32 | "phpunit/phpunit": "3.7.*@stable"
33 | },
34 | "bin": [
35 | "composer/bin/test-reporter"
36 | ],
37 | "type": "library",
38 | "extra": {
39 | "branch-alias": {
40 | "dev-master": "0.2.x-dev"
41 | }
42 | },
43 | "autoload": {
44 | "psr-0": {
45 | "CodeClimate\\Component": "src/",
46 | "CodeClimate\\Bundle": "src/"
47 | }
48 | },
49 | "notification-url": "https://packagist.org/downloads/",
50 | "license": [
51 | "MIT"
52 | ],
53 | "authors": [
54 | {
55 | "name": "Code Climate",
56 | "email": "hello@codeclimate.com",
57 | "homepage": "https://codeclimate.com"
58 | }
59 | ],
60 | "description": "PHP client for reporting test coverage to Code Climate",
61 | "homepage": "https://github.com/codeclimate/php-test-reporter",
62 | "keywords": [
63 | "codeclimate",
64 | "coverage"
65 | ],
66 | "time": "2015-12-17T00:52:54+00:00"
67 | },
68 | {
69 | "name": "doctrine/instantiator",
70 | "version": "1.0.5",
71 | "source": {
72 | "type": "git",
73 | "url": "https://github.com/doctrine/instantiator.git",
74 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
75 | },
76 | "dist": {
77 | "type": "zip",
78 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
79 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
80 | "shasum": ""
81 | },
82 | "require": {
83 | "php": ">=5.3,<8.0-DEV"
84 | },
85 | "require-dev": {
86 | "athletic/athletic": "~0.1.8",
87 | "ext-pdo": "*",
88 | "ext-phar": "*",
89 | "phpunit/phpunit": "~4.0",
90 | "squizlabs/php_codesniffer": "~2.0"
91 | },
92 | "type": "library",
93 | "extra": {
94 | "branch-alias": {
95 | "dev-master": "1.0.x-dev"
96 | }
97 | },
98 | "autoload": {
99 | "psr-4": {
100 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
101 | }
102 | },
103 | "notification-url": "https://packagist.org/downloads/",
104 | "license": [
105 | "MIT"
106 | ],
107 | "authors": [
108 | {
109 | "name": "Marco Pivetta",
110 | "email": "ocramius@gmail.com",
111 | "homepage": "http://ocramius.github.com/"
112 | }
113 | ],
114 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
115 | "homepage": "https://github.com/doctrine/instantiator",
116 | "keywords": [
117 | "constructor",
118 | "instantiate"
119 | ],
120 | "support": {
121 | "issues": "https://github.com/doctrine/instantiator/issues",
122 | "source": "https://github.com/doctrine/instantiator/tree/master"
123 | },
124 | "time": "2015-06-14T21:17:01+00:00"
125 | },
126 | {
127 | "name": "guzzle/guzzle",
128 | "version": "v3.9.3",
129 | "source": {
130 | "type": "git",
131 | "url": "https://github.com/guzzle/guzzle3.git",
132 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
133 | },
134 | "dist": {
135 | "type": "zip",
136 | "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
137 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
138 | "shasum": ""
139 | },
140 | "require": {
141 | "ext-curl": "*",
142 | "php": ">=5.3.3",
143 | "symfony/event-dispatcher": "~2.1"
144 | },
145 | "replace": {
146 | "guzzle/batch": "self.version",
147 | "guzzle/cache": "self.version",
148 | "guzzle/common": "self.version",
149 | "guzzle/http": "self.version",
150 | "guzzle/inflection": "self.version",
151 | "guzzle/iterator": "self.version",
152 | "guzzle/log": "self.version",
153 | "guzzle/parser": "self.version",
154 | "guzzle/plugin": "self.version",
155 | "guzzle/plugin-async": "self.version",
156 | "guzzle/plugin-backoff": "self.version",
157 | "guzzle/plugin-cache": "self.version",
158 | "guzzle/plugin-cookie": "self.version",
159 | "guzzle/plugin-curlauth": "self.version",
160 | "guzzle/plugin-error-response": "self.version",
161 | "guzzle/plugin-history": "self.version",
162 | "guzzle/plugin-log": "self.version",
163 | "guzzle/plugin-md5": "self.version",
164 | "guzzle/plugin-mock": "self.version",
165 | "guzzle/plugin-oauth": "self.version",
166 | "guzzle/service": "self.version",
167 | "guzzle/stream": "self.version"
168 | },
169 | "require-dev": {
170 | "doctrine/cache": "~1.3",
171 | "monolog/monolog": "~1.0",
172 | "phpunit/phpunit": "3.7.*",
173 | "psr/log": "~1.0",
174 | "symfony/class-loader": "~2.1",
175 | "zendframework/zend-cache": "2.*,<2.3",
176 | "zendframework/zend-log": "2.*,<2.3"
177 | },
178 | "suggest": {
179 | "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
180 | },
181 | "type": "library",
182 | "extra": {
183 | "branch-alias": {
184 | "dev-master": "3.9-dev"
185 | }
186 | },
187 | "autoload": {
188 | "psr-0": {
189 | "Guzzle": "src/",
190 | "Guzzle\\Tests": "tests/"
191 | }
192 | },
193 | "notification-url": "https://packagist.org/downloads/",
194 | "license": [
195 | "MIT"
196 | ],
197 | "authors": [
198 | {
199 | "name": "Michael Dowling",
200 | "email": "mtdowling@gmail.com",
201 | "homepage": "https://github.com/mtdowling"
202 | },
203 | {
204 | "name": "Guzzle Community",
205 | "homepage": "https://github.com/guzzle/guzzle/contributors"
206 | }
207 | ],
208 | "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
209 | "homepage": "http://guzzlephp.org/",
210 | "keywords": [
211 | "client",
212 | "curl",
213 | "framework",
214 | "http",
215 | "http client",
216 | "rest",
217 | "web service"
218 | ],
219 | "time": "2015-03-18T18:23:50+00:00"
220 | },
221 | {
222 | "name": "myclabs/deep-copy",
223 | "version": "1.7.0",
224 | "source": {
225 | "type": "git",
226 | "url": "https://github.com/myclabs/DeepCopy.git",
227 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e"
228 | },
229 | "dist": {
230 | "type": "zip",
231 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
232 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
233 | "shasum": ""
234 | },
235 | "require": {
236 | "php": "^5.6 || ^7.0"
237 | },
238 | "require-dev": {
239 | "doctrine/collections": "^1.0",
240 | "doctrine/common": "^2.6",
241 | "phpunit/phpunit": "^4.1"
242 | },
243 | "type": "library",
244 | "autoload": {
245 | "files": [
246 | "src/DeepCopy/deep_copy.php"
247 | ],
248 | "psr-4": {
249 | "DeepCopy\\": "src/DeepCopy/"
250 | }
251 | },
252 | "notification-url": "https://packagist.org/downloads/",
253 | "license": [
254 | "MIT"
255 | ],
256 | "description": "Create deep copies (clones) of your objects",
257 | "keywords": [
258 | "clone",
259 | "copy",
260 | "duplicate",
261 | "object",
262 | "object graph"
263 | ],
264 | "support": {
265 | "issues": "https://github.com/myclabs/DeepCopy/issues",
266 | "source": "https://github.com/myclabs/DeepCopy/tree/1.x"
267 | },
268 | "time": "2017-10-19T19:58:43+00:00"
269 | },
270 | {
271 | "name": "phpdocumentor/reflection-common",
272 | "version": "1.0.1",
273 | "source": {
274 | "type": "git",
275 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
276 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
277 | },
278 | "dist": {
279 | "type": "zip",
280 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
281 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
282 | "shasum": ""
283 | },
284 | "require": {
285 | "php": ">=5.5"
286 | },
287 | "require-dev": {
288 | "phpunit/phpunit": "^4.6"
289 | },
290 | "type": "library",
291 | "extra": {
292 | "branch-alias": {
293 | "dev-master": "1.0.x-dev"
294 | }
295 | },
296 | "autoload": {
297 | "psr-4": {
298 | "phpDocumentor\\Reflection\\": [
299 | "src"
300 | ]
301 | }
302 | },
303 | "notification-url": "https://packagist.org/downloads/",
304 | "license": [
305 | "MIT"
306 | ],
307 | "authors": [
308 | {
309 | "name": "Jaap van Otterdijk",
310 | "email": "opensource@ijaap.nl"
311 | }
312 | ],
313 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
314 | "homepage": "http://www.phpdoc.org",
315 | "keywords": [
316 | "FQSEN",
317 | "phpDocumentor",
318 | "phpdoc",
319 | "reflection",
320 | "static analysis"
321 | ],
322 | "support": {
323 | "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
324 | "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master"
325 | },
326 | "time": "2017-09-11T18:02:19+00:00"
327 | },
328 | {
329 | "name": "phpdocumentor/reflection-docblock",
330 | "version": "4.3.4",
331 | "source": {
332 | "type": "git",
333 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
334 | "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c"
335 | },
336 | "dist": {
337 | "type": "zip",
338 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c",
339 | "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c",
340 | "shasum": ""
341 | },
342 | "require": {
343 | "php": "^7.0",
344 | "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0",
345 | "phpdocumentor/type-resolver": "~0.4 || ^1.0.0",
346 | "webmozart/assert": "^1.0"
347 | },
348 | "require-dev": {
349 | "doctrine/instantiator": "^1.0.5",
350 | "mockery/mockery": "^1.0",
351 | "phpdocumentor/type-resolver": "0.4.*",
352 | "phpunit/phpunit": "^6.4"
353 | },
354 | "type": "library",
355 | "extra": {
356 | "branch-alias": {
357 | "dev-master": "4.x-dev"
358 | }
359 | },
360 | "autoload": {
361 | "psr-4": {
362 | "phpDocumentor\\Reflection\\": [
363 | "src/"
364 | ]
365 | }
366 | },
367 | "notification-url": "https://packagist.org/downloads/",
368 | "license": [
369 | "MIT"
370 | ],
371 | "authors": [
372 | {
373 | "name": "Mike van Riel",
374 | "email": "me@mikevanriel.com"
375 | }
376 | ],
377 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
378 | "support": {
379 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
380 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/4.x"
381 | },
382 | "time": "2019-12-28T18:55:12+00:00"
383 | },
384 | {
385 | "name": "phpdocumentor/type-resolver",
386 | "version": "0.5.1",
387 | "source": {
388 | "type": "git",
389 | "url": "https://github.com/phpDocumentor/TypeResolver.git",
390 | "reference": "cf842904952e64e703800d094cdf34e715a8a3ae"
391 | },
392 | "dist": {
393 | "type": "zip",
394 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/cf842904952e64e703800d094cdf34e715a8a3ae",
395 | "reference": "cf842904952e64e703800d094cdf34e715a8a3ae",
396 | "shasum": ""
397 | },
398 | "require": {
399 | "php": "^7.0",
400 | "phpdocumentor/reflection-common": "^1.0"
401 | },
402 | "require-dev": {
403 | "mockery/mockery": "^1.0",
404 | "phpunit/phpunit": "^6.4"
405 | },
406 | "type": "library",
407 | "extra": {
408 | "branch-alias": {
409 | "dev-master": "1.0.x-dev"
410 | }
411 | },
412 | "autoload": {
413 | "psr-4": {
414 | "phpDocumentor\\Reflection\\": "src"
415 | }
416 | },
417 | "notification-url": "https://packagist.org/downloads/",
418 | "license": [
419 | "MIT"
420 | ],
421 | "authors": [
422 | {
423 | "name": "Mike van Riel",
424 | "email": "me@mikevanriel.com"
425 | }
426 | ],
427 | "support": {
428 | "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
429 | "source": "https://github.com/phpDocumentor/TypeResolver/tree/master"
430 | },
431 | "time": "2017-12-30T13:23:38+00:00"
432 | },
433 | {
434 | "name": "phpspec/prophecy",
435 | "version": "v1.10.3",
436 | "source": {
437 | "type": "git",
438 | "url": "https://github.com/phpspec/prophecy.git",
439 | "reference": "451c3cd1418cf640de218914901e51b064abb093"
440 | },
441 | "dist": {
442 | "type": "zip",
443 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
444 | "reference": "451c3cd1418cf640de218914901e51b064abb093",
445 | "shasum": ""
446 | },
447 | "require": {
448 | "doctrine/instantiator": "^1.0.2",
449 | "php": "^5.3|^7.0",
450 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
451 | "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
452 | "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
453 | },
454 | "require-dev": {
455 | "phpspec/phpspec": "^2.5 || ^3.2",
456 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
457 | },
458 | "type": "library",
459 | "extra": {
460 | "branch-alias": {
461 | "dev-master": "1.10.x-dev"
462 | }
463 | },
464 | "autoload": {
465 | "psr-4": {
466 | "Prophecy\\": "src/Prophecy"
467 | }
468 | },
469 | "notification-url": "https://packagist.org/downloads/",
470 | "license": [
471 | "MIT"
472 | ],
473 | "authors": [
474 | {
475 | "name": "Konstantin Kudryashov",
476 | "email": "ever.zet@gmail.com",
477 | "homepage": "http://everzet.com"
478 | },
479 | {
480 | "name": "Marcello Duarte",
481 | "email": "marcello.duarte@gmail.com"
482 | }
483 | ],
484 | "description": "Highly opinionated mocking framework for PHP 5.3+",
485 | "homepage": "https://github.com/phpspec/prophecy",
486 | "keywords": [
487 | "Double",
488 | "Dummy",
489 | "fake",
490 | "mock",
491 | "spy",
492 | "stub"
493 | ],
494 | "support": {
495 | "issues": "https://github.com/phpspec/prophecy/issues",
496 | "source": "https://github.com/phpspec/prophecy/tree/v1.10.3"
497 | },
498 | "time": "2020-03-05T15:02:03+00:00"
499 | },
500 | {
501 | "name": "phpunit/php-code-coverage",
502 | "version": "4.0.8",
503 | "source": {
504 | "type": "git",
505 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
506 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d"
507 | },
508 | "dist": {
509 | "type": "zip",
510 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
511 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
512 | "shasum": ""
513 | },
514 | "require": {
515 | "ext-dom": "*",
516 | "ext-xmlwriter": "*",
517 | "php": "^5.6 || ^7.0",
518 | "phpunit/php-file-iterator": "^1.3",
519 | "phpunit/php-text-template": "^1.2",
520 | "phpunit/php-token-stream": "^1.4.2 || ^2.0",
521 | "sebastian/code-unit-reverse-lookup": "^1.0",
522 | "sebastian/environment": "^1.3.2 || ^2.0",
523 | "sebastian/version": "^1.0 || ^2.0"
524 | },
525 | "require-dev": {
526 | "ext-xdebug": "^2.1.4",
527 | "phpunit/phpunit": "^5.7"
528 | },
529 | "suggest": {
530 | "ext-xdebug": "^2.5.1"
531 | },
532 | "type": "library",
533 | "extra": {
534 | "branch-alias": {
535 | "dev-master": "4.0.x-dev"
536 | }
537 | },
538 | "autoload": {
539 | "classmap": [
540 | "src/"
541 | ]
542 | },
543 | "notification-url": "https://packagist.org/downloads/",
544 | "license": [
545 | "BSD-3-Clause"
546 | ],
547 | "authors": [
548 | {
549 | "name": "Sebastian Bergmann",
550 | "email": "sb@sebastian-bergmann.de",
551 | "role": "lead"
552 | }
553 | ],
554 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
555 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
556 | "keywords": [
557 | "coverage",
558 | "testing",
559 | "xunit"
560 | ],
561 | "support": {
562 | "irc": "irc://irc.freenode.net/phpunit",
563 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
564 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/4.0"
565 | },
566 | "time": "2017-04-02T07:44:40+00:00"
567 | },
568 | {
569 | "name": "phpunit/php-file-iterator",
570 | "version": "1.4.5",
571 | "source": {
572 | "type": "git",
573 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
574 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
575 | },
576 | "dist": {
577 | "type": "zip",
578 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
579 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
580 | "shasum": ""
581 | },
582 | "require": {
583 | "php": ">=5.3.3"
584 | },
585 | "type": "library",
586 | "extra": {
587 | "branch-alias": {
588 | "dev-master": "1.4.x-dev"
589 | }
590 | },
591 | "autoload": {
592 | "classmap": [
593 | "src/"
594 | ]
595 | },
596 | "notification-url": "https://packagist.org/downloads/",
597 | "license": [
598 | "BSD-3-Clause"
599 | ],
600 | "authors": [
601 | {
602 | "name": "Sebastian Bergmann",
603 | "email": "sb@sebastian-bergmann.de",
604 | "role": "lead"
605 | }
606 | ],
607 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
608 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
609 | "keywords": [
610 | "filesystem",
611 | "iterator"
612 | ],
613 | "support": {
614 | "irc": "irc://irc.freenode.net/phpunit",
615 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
616 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5"
617 | },
618 | "time": "2017-11-27T13:52:08+00:00"
619 | },
620 | {
621 | "name": "phpunit/php-text-template",
622 | "version": "1.2.1",
623 | "source": {
624 | "type": "git",
625 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
626 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
627 | },
628 | "dist": {
629 | "type": "zip",
630 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
631 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
632 | "shasum": ""
633 | },
634 | "require": {
635 | "php": ">=5.3.3"
636 | },
637 | "type": "library",
638 | "autoload": {
639 | "classmap": [
640 | "src/"
641 | ]
642 | },
643 | "notification-url": "https://packagist.org/downloads/",
644 | "license": [
645 | "BSD-3-Clause"
646 | ],
647 | "authors": [
648 | {
649 | "name": "Sebastian Bergmann",
650 | "email": "sebastian@phpunit.de",
651 | "role": "lead"
652 | }
653 | ],
654 | "description": "Simple template engine.",
655 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
656 | "keywords": [
657 | "template"
658 | ],
659 | "support": {
660 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
661 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1"
662 | },
663 | "time": "2015-06-21T13:50:34+00:00"
664 | },
665 | {
666 | "name": "phpunit/php-timer",
667 | "version": "1.0.9",
668 | "source": {
669 | "type": "git",
670 | "url": "https://github.com/sebastianbergmann/php-timer.git",
671 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
672 | },
673 | "dist": {
674 | "type": "zip",
675 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
676 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
677 | "shasum": ""
678 | },
679 | "require": {
680 | "php": "^5.3.3 || ^7.0"
681 | },
682 | "require-dev": {
683 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
684 | },
685 | "type": "library",
686 | "extra": {
687 | "branch-alias": {
688 | "dev-master": "1.0-dev"
689 | }
690 | },
691 | "autoload": {
692 | "classmap": [
693 | "src/"
694 | ]
695 | },
696 | "notification-url": "https://packagist.org/downloads/",
697 | "license": [
698 | "BSD-3-Clause"
699 | ],
700 | "authors": [
701 | {
702 | "name": "Sebastian Bergmann",
703 | "email": "sb@sebastian-bergmann.de",
704 | "role": "lead"
705 | }
706 | ],
707 | "description": "Utility class for timing",
708 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
709 | "keywords": [
710 | "timer"
711 | ],
712 | "support": {
713 | "issues": "https://github.com/sebastianbergmann/php-timer/issues",
714 | "source": "https://github.com/sebastianbergmann/php-timer/tree/master"
715 | },
716 | "time": "2017-02-26T11:10:40+00:00"
717 | },
718 | {
719 | "name": "phpunit/php-token-stream",
720 | "version": "2.0.2",
721 | "source": {
722 | "type": "git",
723 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
724 | "reference": "791198a2c6254db10131eecfe8c06670700904db"
725 | },
726 | "dist": {
727 | "type": "zip",
728 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db",
729 | "reference": "791198a2c6254db10131eecfe8c06670700904db",
730 | "shasum": ""
731 | },
732 | "require": {
733 | "ext-tokenizer": "*",
734 | "php": "^7.0"
735 | },
736 | "require-dev": {
737 | "phpunit/phpunit": "^6.2.4"
738 | },
739 | "type": "library",
740 | "extra": {
741 | "branch-alias": {
742 | "dev-master": "2.0-dev"
743 | }
744 | },
745 | "autoload": {
746 | "classmap": [
747 | "src/"
748 | ]
749 | },
750 | "notification-url": "https://packagist.org/downloads/",
751 | "license": [
752 | "BSD-3-Clause"
753 | ],
754 | "authors": [
755 | {
756 | "name": "Sebastian Bergmann",
757 | "email": "sebastian@phpunit.de"
758 | }
759 | ],
760 | "description": "Wrapper around PHP's tokenizer extension.",
761 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
762 | "keywords": [
763 | "tokenizer"
764 | ],
765 | "support": {
766 | "issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
767 | "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master"
768 | },
769 | "abandoned": true,
770 | "time": "2017-11-27T05:48:46+00:00"
771 | },
772 | {
773 | "name": "phpunit/phpunit",
774 | "version": "5.6.3",
775 | "source": {
776 | "type": "git",
777 | "url": "https://github.com/sebastianbergmann/phpunit.git",
778 | "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c"
779 | },
780 | "dist": {
781 | "type": "zip",
782 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9de0dbafeb6b1391b391fbb034734cb0af9f67c",
783 | "reference": "a9de0dbafeb6b1391b391fbb034734cb0af9f67c",
784 | "shasum": ""
785 | },
786 | "require": {
787 | "ext-dom": "*",
788 | "ext-json": "*",
789 | "ext-libxml": "*",
790 | "ext-mbstring": "*",
791 | "ext-xml": "*",
792 | "myclabs/deep-copy": "~1.3",
793 | "php": "^5.6 || ^7.0",
794 | "phpspec/prophecy": "^1.3.1",
795 | "phpunit/php-code-coverage": "^4.0.1",
796 | "phpunit/php-file-iterator": "~1.4",
797 | "phpunit/php-text-template": "~1.2",
798 | "phpunit/php-timer": "^1.0.6",
799 | "phpunit/phpunit-mock-objects": "^3.2",
800 | "sebastian/comparator": "~1.1",
801 | "sebastian/diff": "~1.2",
802 | "sebastian/environment": "^1.3 || ^2.0",
803 | "sebastian/exporter": "~1.2",
804 | "sebastian/global-state": "~1.0",
805 | "sebastian/object-enumerator": "~1.0",
806 | "sebastian/resource-operations": "~1.0",
807 | "sebastian/version": "~1.0|~2.0",
808 | "symfony/yaml": "~2.1|~3.0"
809 | },
810 | "conflict": {
811 | "phpdocumentor/reflection-docblock": "3.0.2"
812 | },
813 | "require-dev": {
814 | "ext-pdo": "*"
815 | },
816 | "suggest": {
817 | "ext-xdebug": "*",
818 | "phpunit/php-invoker": "~1.1"
819 | },
820 | "bin": [
821 | "phpunit"
822 | ],
823 | "type": "library",
824 | "extra": {
825 | "branch-alias": {
826 | "dev-master": "5.6.x-dev"
827 | }
828 | },
829 | "autoload": {
830 | "classmap": [
831 | "src/"
832 | ]
833 | },
834 | "notification-url": "https://packagist.org/downloads/",
835 | "license": [
836 | "BSD-3-Clause"
837 | ],
838 | "authors": [
839 | {
840 | "name": "Sebastian Bergmann",
841 | "email": "sebastian@phpunit.de",
842 | "role": "lead"
843 | }
844 | ],
845 | "description": "The PHP Unit Testing framework.",
846 | "homepage": "https://phpunit.de/",
847 | "keywords": [
848 | "phpunit",
849 | "testing",
850 | "xunit"
851 | ],
852 | "support": {
853 | "issues": "https://github.com/sebastianbergmann/phpunit/issues",
854 | "source": "https://github.com/sebastianbergmann/phpunit/tree/5.6.3"
855 | },
856 | "time": "2016-11-14T06:39:40+00:00"
857 | },
858 | {
859 | "name": "phpunit/phpunit-mock-objects",
860 | "version": "3.4.4",
861 | "source": {
862 | "type": "git",
863 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
864 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118"
865 | },
866 | "dist": {
867 | "type": "zip",
868 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118",
869 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118",
870 | "shasum": ""
871 | },
872 | "require": {
873 | "doctrine/instantiator": "^1.0.2",
874 | "php": "^5.6 || ^7.0",
875 | "phpunit/php-text-template": "^1.2",
876 | "sebastian/exporter": "^1.2 || ^2.0"
877 | },
878 | "conflict": {
879 | "phpunit/phpunit": "<5.4.0"
880 | },
881 | "require-dev": {
882 | "phpunit/phpunit": "^5.4"
883 | },
884 | "suggest": {
885 | "ext-soap": "*"
886 | },
887 | "type": "library",
888 | "extra": {
889 | "branch-alias": {
890 | "dev-master": "3.2.x-dev"
891 | }
892 | },
893 | "autoload": {
894 | "classmap": [
895 | "src/"
896 | ]
897 | },
898 | "notification-url": "https://packagist.org/downloads/",
899 | "license": [
900 | "BSD-3-Clause"
901 | ],
902 | "authors": [
903 | {
904 | "name": "Sebastian Bergmann",
905 | "email": "sb@sebastian-bergmann.de",
906 | "role": "lead"
907 | }
908 | ],
909 | "description": "Mock Object library for PHPUnit",
910 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
911 | "keywords": [
912 | "mock",
913 | "xunit"
914 | ],
915 | "support": {
916 | "irc": "irc://irc.freenode.net/phpunit",
917 | "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues",
918 | "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/3.4"
919 | },
920 | "abandoned": true,
921 | "time": "2017-06-30T09:13:00+00:00"
922 | },
923 | {
924 | "name": "psr/log",
925 | "version": "1.0.0",
926 | "source": {
927 | "type": "git",
928 | "url": "https://github.com/php-fig/log.git",
929 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
930 | },
931 | "dist": {
932 | "type": "zip",
933 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
934 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
935 | "shasum": ""
936 | },
937 | "type": "library",
938 | "autoload": {
939 | "psr-0": {
940 | "Psr\\Log\\": ""
941 | }
942 | },
943 | "notification-url": "https://packagist.org/downloads/",
944 | "license": [
945 | "MIT"
946 | ],
947 | "authors": [
948 | {
949 | "name": "PHP-FIG",
950 | "homepage": "http://www.php-fig.org/"
951 | }
952 | ],
953 | "description": "Common interface for logging libraries",
954 | "keywords": [
955 | "log",
956 | "psr",
957 | "psr-3"
958 | ],
959 | "time": "2012-12-21T11:40:51+00:00"
960 | },
961 | {
962 | "name": "satooshi/php-coveralls",
963 | "version": "v0.6.1",
964 | "source": {
965 | "type": "git",
966 | "url": "https://github.com/satooshi/php-coveralls.git",
967 | "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760"
968 | },
969 | "dist": {
970 | "type": "zip",
971 | "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760",
972 | "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760",
973 | "shasum": ""
974 | },
975 | "require": {
976 | "ext-curl": "*",
977 | "ext-json": "*",
978 | "ext-simplexml": "*",
979 | "guzzle/guzzle": ">=3.0",
980 | "php": ">=5.3",
981 | "psr/log": "1.0.0",
982 | "symfony/config": ">=2.0",
983 | "symfony/console": ">=2.0",
984 | "symfony/stopwatch": ">=2.2",
985 | "symfony/yaml": ">=2.0"
986 | },
987 | "require-dev": {
988 | "apigen/apigen": "2.8.*@stable",
989 | "pdepend/pdepend": "dev-master",
990 | "phpmd/phpmd": "dev-master",
991 | "phpunit/php-invoker": ">=1.1.0,<1.2.0",
992 | "phpunit/phpunit": "3.7.*@stable",
993 | "sebastian/finder-facade": "dev-master",
994 | "sebastian/phpcpd": "1.4.*@stable",
995 | "squizlabs/php_codesniffer": "1.4.*@stable",
996 | "theseer/fdomdocument": "dev-master"
997 | },
998 | "bin": [
999 | "composer/bin/coveralls"
1000 | ],
1001 | "type": "library",
1002 | "autoload": {
1003 | "psr-0": {
1004 | "Contrib\\Component": "src/",
1005 | "Contrib\\Bundle": "src/"
1006 | }
1007 | },
1008 | "notification-url": "https://packagist.org/downloads/",
1009 | "license": [
1010 | "MIT"
1011 | ],
1012 | "authors": [
1013 | {
1014 | "name": "Kitamura Satoshi",
1015 | "email": "with.no.parachute@gmail.com",
1016 | "homepage": "https://www.facebook.com/satooshi.jp"
1017 | }
1018 | ],
1019 | "description": "PHP client library for Coveralls API",
1020 | "homepage": "https://github.com/satooshi/php-coveralls",
1021 | "keywords": [
1022 | "ci",
1023 | "coverage",
1024 | "github",
1025 | "test"
1026 | ],
1027 | "time": "2013-05-04T08:07:33+00:00"
1028 | },
1029 | {
1030 | "name": "sebastian/code-unit-reverse-lookup",
1031 | "version": "1.0.2",
1032 | "source": {
1033 | "type": "git",
1034 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
1035 | "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619"
1036 | },
1037 | "dist": {
1038 | "type": "zip",
1039 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619",
1040 | "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619",
1041 | "shasum": ""
1042 | },
1043 | "require": {
1044 | "php": ">=5.6"
1045 | },
1046 | "require-dev": {
1047 | "phpunit/phpunit": "^8.5"
1048 | },
1049 | "type": "library",
1050 | "extra": {
1051 | "branch-alias": {
1052 | "dev-master": "1.0.x-dev"
1053 | }
1054 | },
1055 | "autoload": {
1056 | "classmap": [
1057 | "src/"
1058 | ]
1059 | },
1060 | "notification-url": "https://packagist.org/downloads/",
1061 | "license": [
1062 | "BSD-3-Clause"
1063 | ],
1064 | "authors": [
1065 | {
1066 | "name": "Sebastian Bergmann",
1067 | "email": "sebastian@phpunit.de"
1068 | }
1069 | ],
1070 | "description": "Looks up which function or method a line of code belongs to",
1071 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
1072 | "support": {
1073 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
1074 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2"
1075 | },
1076 | "funding": [
1077 | {
1078 | "url": "https://github.com/sebastianbergmann",
1079 | "type": "github"
1080 | }
1081 | ],
1082 | "time": "2020-11-30T08:15:22+00:00"
1083 | },
1084 | {
1085 | "name": "sebastian/comparator",
1086 | "version": "1.2.4",
1087 | "source": {
1088 | "type": "git",
1089 | "url": "https://github.com/sebastianbergmann/comparator.git",
1090 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
1091 | },
1092 | "dist": {
1093 | "type": "zip",
1094 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
1095 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
1096 | "shasum": ""
1097 | },
1098 | "require": {
1099 | "php": ">=5.3.3",
1100 | "sebastian/diff": "~1.2",
1101 | "sebastian/exporter": "~1.2 || ~2.0"
1102 | },
1103 | "require-dev": {
1104 | "phpunit/phpunit": "~4.4"
1105 | },
1106 | "type": "library",
1107 | "extra": {
1108 | "branch-alias": {
1109 | "dev-master": "1.2.x-dev"
1110 | }
1111 | },
1112 | "autoload": {
1113 | "classmap": [
1114 | "src/"
1115 | ]
1116 | },
1117 | "notification-url": "https://packagist.org/downloads/",
1118 | "license": [
1119 | "BSD-3-Clause"
1120 | ],
1121 | "authors": [
1122 | {
1123 | "name": "Jeff Welch",
1124 | "email": "whatthejeff@gmail.com"
1125 | },
1126 | {
1127 | "name": "Volker Dusch",
1128 | "email": "github@wallbash.com"
1129 | },
1130 | {
1131 | "name": "Bernhard Schussek",
1132 | "email": "bschussek@2bepublished.at"
1133 | },
1134 | {
1135 | "name": "Sebastian Bergmann",
1136 | "email": "sebastian@phpunit.de"
1137 | }
1138 | ],
1139 | "description": "Provides the functionality to compare PHP values for equality",
1140 | "homepage": "http://www.github.com/sebastianbergmann/comparator",
1141 | "keywords": [
1142 | "comparator",
1143 | "compare",
1144 | "equality"
1145 | ],
1146 | "support": {
1147 | "issues": "https://github.com/sebastianbergmann/comparator/issues",
1148 | "source": "https://github.com/sebastianbergmann/comparator/tree/1.2"
1149 | },
1150 | "time": "2017-01-29T09:50:25+00:00"
1151 | },
1152 | {
1153 | "name": "sebastian/diff",
1154 | "version": "1.4.3",
1155 | "source": {
1156 | "type": "git",
1157 | "url": "https://github.com/sebastianbergmann/diff.git",
1158 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
1159 | },
1160 | "dist": {
1161 | "type": "zip",
1162 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
1163 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
1164 | "shasum": ""
1165 | },
1166 | "require": {
1167 | "php": "^5.3.3 || ^7.0"
1168 | },
1169 | "require-dev": {
1170 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
1171 | },
1172 | "type": "library",
1173 | "extra": {
1174 | "branch-alias": {
1175 | "dev-master": "1.4-dev"
1176 | }
1177 | },
1178 | "autoload": {
1179 | "classmap": [
1180 | "src/"
1181 | ]
1182 | },
1183 | "notification-url": "https://packagist.org/downloads/",
1184 | "license": [
1185 | "BSD-3-Clause"
1186 | ],
1187 | "authors": [
1188 | {
1189 | "name": "Kore Nordmann",
1190 | "email": "mail@kore-nordmann.de"
1191 | },
1192 | {
1193 | "name": "Sebastian Bergmann",
1194 | "email": "sebastian@phpunit.de"
1195 | }
1196 | ],
1197 | "description": "Diff implementation",
1198 | "homepage": "https://github.com/sebastianbergmann/diff",
1199 | "keywords": [
1200 | "diff"
1201 | ],
1202 | "support": {
1203 | "issues": "https://github.com/sebastianbergmann/diff/issues",
1204 | "source": "https://github.com/sebastianbergmann/diff/tree/1.4"
1205 | },
1206 | "time": "2017-05-22T07:24:03+00:00"
1207 | },
1208 | {
1209 | "name": "sebastian/environment",
1210 | "version": "2.0.0",
1211 | "source": {
1212 | "type": "git",
1213 | "url": "https://github.com/sebastianbergmann/environment.git",
1214 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
1215 | },
1216 | "dist": {
1217 | "type": "zip",
1218 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
1219 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
1220 | "shasum": ""
1221 | },
1222 | "require": {
1223 | "php": "^5.6 || ^7.0"
1224 | },
1225 | "require-dev": {
1226 | "phpunit/phpunit": "^5.0"
1227 | },
1228 | "type": "library",
1229 | "extra": {
1230 | "branch-alias": {
1231 | "dev-master": "2.0.x-dev"
1232 | }
1233 | },
1234 | "autoload": {
1235 | "classmap": [
1236 | "src/"
1237 | ]
1238 | },
1239 | "notification-url": "https://packagist.org/downloads/",
1240 | "license": [
1241 | "BSD-3-Clause"
1242 | ],
1243 | "authors": [
1244 | {
1245 | "name": "Sebastian Bergmann",
1246 | "email": "sebastian@phpunit.de"
1247 | }
1248 | ],
1249 | "description": "Provides functionality to handle HHVM/PHP environments",
1250 | "homepage": "http://www.github.com/sebastianbergmann/environment",
1251 | "keywords": [
1252 | "Xdebug",
1253 | "environment",
1254 | "hhvm"
1255 | ],
1256 | "support": {
1257 | "issues": "https://github.com/sebastianbergmann/environment/issues",
1258 | "source": "https://github.com/sebastianbergmann/environment/tree/master"
1259 | },
1260 | "time": "2016-11-26T07:53:53+00:00"
1261 | },
1262 | {
1263 | "name": "sebastian/exporter",
1264 | "version": "1.2.2",
1265 | "source": {
1266 | "type": "git",
1267 | "url": "https://github.com/sebastianbergmann/exporter.git",
1268 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
1269 | },
1270 | "dist": {
1271 | "type": "zip",
1272 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
1273 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
1274 | "shasum": ""
1275 | },
1276 | "require": {
1277 | "php": ">=5.3.3",
1278 | "sebastian/recursion-context": "~1.0"
1279 | },
1280 | "require-dev": {
1281 | "ext-mbstring": "*",
1282 | "phpunit/phpunit": "~4.4"
1283 | },
1284 | "type": "library",
1285 | "extra": {
1286 | "branch-alias": {
1287 | "dev-master": "1.3.x-dev"
1288 | }
1289 | },
1290 | "autoload": {
1291 | "classmap": [
1292 | "src/"
1293 | ]
1294 | },
1295 | "notification-url": "https://packagist.org/downloads/",
1296 | "license": [
1297 | "BSD-3-Clause"
1298 | ],
1299 | "authors": [
1300 | {
1301 | "name": "Jeff Welch",
1302 | "email": "whatthejeff@gmail.com"
1303 | },
1304 | {
1305 | "name": "Volker Dusch",
1306 | "email": "github@wallbash.com"
1307 | },
1308 | {
1309 | "name": "Bernhard Schussek",
1310 | "email": "bschussek@2bepublished.at"
1311 | },
1312 | {
1313 | "name": "Sebastian Bergmann",
1314 | "email": "sebastian@phpunit.de"
1315 | },
1316 | {
1317 | "name": "Adam Harvey",
1318 | "email": "aharvey@php.net"
1319 | }
1320 | ],
1321 | "description": "Provides the functionality to export PHP variables for visualization",
1322 | "homepage": "http://www.github.com/sebastianbergmann/exporter",
1323 | "keywords": [
1324 | "export",
1325 | "exporter"
1326 | ],
1327 | "support": {
1328 | "issues": "https://github.com/sebastianbergmann/exporter/issues",
1329 | "source": "https://github.com/sebastianbergmann/exporter/tree/master"
1330 | },
1331 | "time": "2016-06-17T09:04:28+00:00"
1332 | },
1333 | {
1334 | "name": "sebastian/global-state",
1335 | "version": "1.1.1",
1336 | "source": {
1337 | "type": "git",
1338 | "url": "https://github.com/sebastianbergmann/global-state.git",
1339 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
1340 | },
1341 | "dist": {
1342 | "type": "zip",
1343 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
1344 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
1345 | "shasum": ""
1346 | },
1347 | "require": {
1348 | "php": ">=5.3.3"
1349 | },
1350 | "require-dev": {
1351 | "phpunit/phpunit": "~4.2"
1352 | },
1353 | "suggest": {
1354 | "ext-uopz": "*"
1355 | },
1356 | "type": "library",
1357 | "extra": {
1358 | "branch-alias": {
1359 | "dev-master": "1.0-dev"
1360 | }
1361 | },
1362 | "autoload": {
1363 | "classmap": [
1364 | "src/"
1365 | ]
1366 | },
1367 | "notification-url": "https://packagist.org/downloads/",
1368 | "license": [
1369 | "BSD-3-Clause"
1370 | ],
1371 | "authors": [
1372 | {
1373 | "name": "Sebastian Bergmann",
1374 | "email": "sebastian@phpunit.de"
1375 | }
1376 | ],
1377 | "description": "Snapshotting of global state",
1378 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1379 | "keywords": [
1380 | "global state"
1381 | ],
1382 | "support": {
1383 | "issues": "https://github.com/sebastianbergmann/global-state/issues",
1384 | "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1"
1385 | },
1386 | "time": "2015-10-12T03:26:01+00:00"
1387 | },
1388 | {
1389 | "name": "sebastian/object-enumerator",
1390 | "version": "1.0.0",
1391 | "source": {
1392 | "type": "git",
1393 | "url": "https://github.com/sebastianbergmann/object-enumerator.git",
1394 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26"
1395 | },
1396 | "dist": {
1397 | "type": "zip",
1398 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26",
1399 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26",
1400 | "shasum": ""
1401 | },
1402 | "require": {
1403 | "php": ">=5.6",
1404 | "sebastian/recursion-context": "~1.0"
1405 | },
1406 | "require-dev": {
1407 | "phpunit/phpunit": "~5"
1408 | },
1409 | "type": "library",
1410 | "extra": {
1411 | "branch-alias": {
1412 | "dev-master": "1.0.x-dev"
1413 | }
1414 | },
1415 | "autoload": {
1416 | "classmap": [
1417 | "src/"
1418 | ]
1419 | },
1420 | "notification-url": "https://packagist.org/downloads/",
1421 | "license": [
1422 | "BSD-3-Clause"
1423 | ],
1424 | "authors": [
1425 | {
1426 | "name": "Sebastian Bergmann",
1427 | "email": "sebastian@phpunit.de"
1428 | }
1429 | ],
1430 | "description": "Traverses array structures and object graphs to enumerate all referenced objects",
1431 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
1432 | "support": {
1433 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
1434 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/master"
1435 | },
1436 | "time": "2016-01-28T13:25:10+00:00"
1437 | },
1438 | {
1439 | "name": "sebastian/recursion-context",
1440 | "version": "1.0.5",
1441 | "source": {
1442 | "type": "git",
1443 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1444 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7"
1445 | },
1446 | "dist": {
1447 | "type": "zip",
1448 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
1449 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
1450 | "shasum": ""
1451 | },
1452 | "require": {
1453 | "php": ">=5.3.3"
1454 | },
1455 | "require-dev": {
1456 | "phpunit/phpunit": "~4.4"
1457 | },
1458 | "type": "library",
1459 | "extra": {
1460 | "branch-alias": {
1461 | "dev-master": "1.0.x-dev"
1462 | }
1463 | },
1464 | "autoload": {
1465 | "classmap": [
1466 | "src/"
1467 | ]
1468 | },
1469 | "notification-url": "https://packagist.org/downloads/",
1470 | "license": [
1471 | "BSD-3-Clause"
1472 | ],
1473 | "authors": [
1474 | {
1475 | "name": "Jeff Welch",
1476 | "email": "whatthejeff@gmail.com"
1477 | },
1478 | {
1479 | "name": "Sebastian Bergmann",
1480 | "email": "sebastian@phpunit.de"
1481 | },
1482 | {
1483 | "name": "Adam Harvey",
1484 | "email": "aharvey@php.net"
1485 | }
1486 | ],
1487 | "description": "Provides functionality to recursively process PHP variables",
1488 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1489 | "support": {
1490 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
1491 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/master"
1492 | },
1493 | "time": "2016-10-03T07:41:43+00:00"
1494 | },
1495 | {
1496 | "name": "sebastian/resource-operations",
1497 | "version": "1.0.0",
1498 | "source": {
1499 | "type": "git",
1500 | "url": "https://github.com/sebastianbergmann/resource-operations.git",
1501 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
1502 | },
1503 | "dist": {
1504 | "type": "zip",
1505 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
1506 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
1507 | "shasum": ""
1508 | },
1509 | "require": {
1510 | "php": ">=5.6.0"
1511 | },
1512 | "type": "library",
1513 | "extra": {
1514 | "branch-alias": {
1515 | "dev-master": "1.0.x-dev"
1516 | }
1517 | },
1518 | "autoload": {
1519 | "classmap": [
1520 | "src/"
1521 | ]
1522 | },
1523 | "notification-url": "https://packagist.org/downloads/",
1524 | "license": [
1525 | "BSD-3-Clause"
1526 | ],
1527 | "authors": [
1528 | {
1529 | "name": "Sebastian Bergmann",
1530 | "email": "sebastian@phpunit.de"
1531 | }
1532 | ],
1533 | "description": "Provides a list of PHP built-in functions that operate on resources",
1534 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
1535 | "support": {
1536 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
1537 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/master"
1538 | },
1539 | "time": "2015-07-28T20:34:47+00:00"
1540 | },
1541 | {
1542 | "name": "sebastian/version",
1543 | "version": "2.0.1",
1544 | "source": {
1545 | "type": "git",
1546 | "url": "https://github.com/sebastianbergmann/version.git",
1547 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
1548 | },
1549 | "dist": {
1550 | "type": "zip",
1551 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
1552 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
1553 | "shasum": ""
1554 | },
1555 | "require": {
1556 | "php": ">=5.6"
1557 | },
1558 | "type": "library",
1559 | "extra": {
1560 | "branch-alias": {
1561 | "dev-master": "2.0.x-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 | "role": "lead"
1578 | }
1579 | ],
1580 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1581 | "homepage": "https://github.com/sebastianbergmann/version",
1582 | "support": {
1583 | "issues": "https://github.com/sebastianbergmann/version/issues",
1584 | "source": "https://github.com/sebastianbergmann/version/tree/master"
1585 | },
1586 | "time": "2016-10-03T07:35:21+00:00"
1587 | },
1588 | {
1589 | "name": "symfony/config",
1590 | "version": "v3.0.2",
1591 | "source": {
1592 | "type": "git",
1593 | "url": "https://github.com/symfony/config.git",
1594 | "reference": "8c83ff9a2ffbed1e606bc816db11ddc2385a16ee"
1595 | },
1596 | "dist": {
1597 | "type": "zip",
1598 | "url": "https://api.github.com/repos/symfony/config/zipball/8c83ff9a2ffbed1e606bc816db11ddc2385a16ee",
1599 | "reference": "8c83ff9a2ffbed1e606bc816db11ddc2385a16ee",
1600 | "shasum": ""
1601 | },
1602 | "require": {
1603 | "php": ">=5.5.9",
1604 | "symfony/filesystem": "~2.8|~3.0"
1605 | },
1606 | "type": "library",
1607 | "extra": {
1608 | "branch-alias": {
1609 | "dev-master": "3.0-dev"
1610 | }
1611 | },
1612 | "autoload": {
1613 | "psr-4": {
1614 | "Symfony\\Component\\Config\\": ""
1615 | },
1616 | "exclude-from-classmap": [
1617 | "/Tests/"
1618 | ]
1619 | },
1620 | "notification-url": "https://packagist.org/downloads/",
1621 | "license": [
1622 | "MIT"
1623 | ],
1624 | "authors": [
1625 | {
1626 | "name": "Fabien Potencier",
1627 | "email": "fabien@symfony.com"
1628 | },
1629 | {
1630 | "name": "Symfony Community",
1631 | "homepage": "https://symfony.com/contributors"
1632 | }
1633 | ],
1634 | "description": "Symfony Config Component",
1635 | "homepage": "https://symfony.com",
1636 | "time": "2016-01-21T09:38:31+00:00"
1637 | },
1638 | {
1639 | "name": "symfony/console",
1640 | "version": "v3.0.2",
1641 | "source": {
1642 | "type": "git",
1643 | "url": "https://github.com/symfony/console.git",
1644 | "reference": "5a02eaadaa285e2bb727eb6bbdfb8201fcd971b0"
1645 | },
1646 | "dist": {
1647 | "type": "zip",
1648 | "url": "https://api.github.com/repos/symfony/console/zipball/5a02eaadaa285e2bb727eb6bbdfb8201fcd971b0",
1649 | "reference": "5a02eaadaa285e2bb727eb6bbdfb8201fcd971b0",
1650 | "shasum": ""
1651 | },
1652 | "require": {
1653 | "php": ">=5.5.9",
1654 | "symfony/polyfill-mbstring": "~1.0"
1655 | },
1656 | "require-dev": {
1657 | "psr/log": "~1.0",
1658 | "symfony/event-dispatcher": "~2.8|~3.0",
1659 | "symfony/process": "~2.8|~3.0"
1660 | },
1661 | "suggest": {
1662 | "psr/log": "For using the console logger",
1663 | "symfony/event-dispatcher": "",
1664 | "symfony/process": ""
1665 | },
1666 | "type": "library",
1667 | "extra": {
1668 | "branch-alias": {
1669 | "dev-master": "3.0-dev"
1670 | }
1671 | },
1672 | "autoload": {
1673 | "psr-4": {
1674 | "Symfony\\Component\\Console\\": ""
1675 | },
1676 | "exclude-from-classmap": [
1677 | "/Tests/"
1678 | ]
1679 | },
1680 | "notification-url": "https://packagist.org/downloads/",
1681 | "license": [
1682 | "MIT"
1683 | ],
1684 | "authors": [
1685 | {
1686 | "name": "Fabien Potencier",
1687 | "email": "fabien@symfony.com"
1688 | },
1689 | {
1690 | "name": "Symfony Community",
1691 | "homepage": "https://symfony.com/contributors"
1692 | }
1693 | ],
1694 | "description": "Symfony Console Component",
1695 | "homepage": "https://symfony.com",
1696 | "time": "2016-02-02T13:44:19+00:00"
1697 | },
1698 | {
1699 | "name": "symfony/event-dispatcher",
1700 | "version": "v2.8.2",
1701 | "source": {
1702 | "type": "git",
1703 | "url": "https://github.com/symfony/event-dispatcher.git",
1704 | "reference": "ee278f7c851533e58ca307f66305ccb9188aceda"
1705 | },
1706 | "dist": {
1707 | "type": "zip",
1708 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ee278f7c851533e58ca307f66305ccb9188aceda",
1709 | "reference": "ee278f7c851533e58ca307f66305ccb9188aceda",
1710 | "shasum": ""
1711 | },
1712 | "require": {
1713 | "php": ">=5.3.9"
1714 | },
1715 | "require-dev": {
1716 | "psr/log": "~1.0",
1717 | "symfony/config": "~2.0,>=2.0.5|~3.0.0",
1718 | "symfony/dependency-injection": "~2.6|~3.0.0",
1719 | "symfony/expression-language": "~2.6|~3.0.0",
1720 | "symfony/stopwatch": "~2.3|~3.0.0"
1721 | },
1722 | "suggest": {
1723 | "symfony/dependency-injection": "",
1724 | "symfony/http-kernel": ""
1725 | },
1726 | "type": "library",
1727 | "extra": {
1728 | "branch-alias": {
1729 | "dev-master": "2.8-dev"
1730 | }
1731 | },
1732 | "autoload": {
1733 | "psr-4": {
1734 | "Symfony\\Component\\EventDispatcher\\": ""
1735 | },
1736 | "exclude-from-classmap": [
1737 | "/Tests/"
1738 | ]
1739 | },
1740 | "notification-url": "https://packagist.org/downloads/",
1741 | "license": [
1742 | "MIT"
1743 | ],
1744 | "authors": [
1745 | {
1746 | "name": "Fabien Potencier",
1747 | "email": "fabien@symfony.com"
1748 | },
1749 | {
1750 | "name": "Symfony Community",
1751 | "homepage": "https://symfony.com/contributors"
1752 | }
1753 | ],
1754 | "description": "Symfony EventDispatcher Component",
1755 | "homepage": "https://symfony.com",
1756 | "time": "2016-01-13T10:28:07+00:00"
1757 | },
1758 | {
1759 | "name": "symfony/filesystem",
1760 | "version": "v3.0.2",
1761 | "source": {
1762 | "type": "git",
1763 | "url": "https://github.com/symfony/filesystem.git",
1764 | "reference": "064ac12afd2ceb8a2c1bfb7bed8e931c6dd1997f"
1765 | },
1766 | "dist": {
1767 | "type": "zip",
1768 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/064ac12afd2ceb8a2c1bfb7bed8e931c6dd1997f",
1769 | "reference": "064ac12afd2ceb8a2c1bfb7bed8e931c6dd1997f",
1770 | "shasum": ""
1771 | },
1772 | "require": {
1773 | "php": ">=5.5.9"
1774 | },
1775 | "type": "library",
1776 | "extra": {
1777 | "branch-alias": {
1778 | "dev-master": "3.0-dev"
1779 | }
1780 | },
1781 | "autoload": {
1782 | "psr-4": {
1783 | "Symfony\\Component\\Filesystem\\": ""
1784 | },
1785 | "exclude-from-classmap": [
1786 | "/Tests/"
1787 | ]
1788 | },
1789 | "notification-url": "https://packagist.org/downloads/",
1790 | "license": [
1791 | "MIT"
1792 | ],
1793 | "authors": [
1794 | {
1795 | "name": "Fabien Potencier",
1796 | "email": "fabien@symfony.com"
1797 | },
1798 | {
1799 | "name": "Symfony Community",
1800 | "homepage": "https://symfony.com/contributors"
1801 | }
1802 | ],
1803 | "description": "Symfony Filesystem Component",
1804 | "homepage": "https://symfony.com",
1805 | "time": "2016-01-27T11:34:55+00:00"
1806 | },
1807 | {
1808 | "name": "symfony/polyfill-ctype",
1809 | "version": "v1.19.0",
1810 | "source": {
1811 | "type": "git",
1812 | "url": "https://github.com/symfony/polyfill-ctype.git",
1813 | "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
1814 | },
1815 | "dist": {
1816 | "type": "zip",
1817 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
1818 | "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
1819 | "shasum": ""
1820 | },
1821 | "require": {
1822 | "php": ">=5.3.3"
1823 | },
1824 | "suggest": {
1825 | "ext-ctype": "For best performance"
1826 | },
1827 | "type": "library",
1828 | "extra": {
1829 | "branch-alias": {
1830 | "dev-main": "1.19-dev"
1831 | },
1832 | "thanks": {
1833 | "name": "symfony/polyfill",
1834 | "url": "https://github.com/symfony/polyfill"
1835 | }
1836 | },
1837 | "autoload": {
1838 | "files": [
1839 | "bootstrap.php"
1840 | ],
1841 | "psr-4": {
1842 | "Symfony\\Polyfill\\Ctype\\": ""
1843 | }
1844 | },
1845 | "notification-url": "https://packagist.org/downloads/",
1846 | "license": [
1847 | "MIT"
1848 | ],
1849 | "authors": [
1850 | {
1851 | "name": "Gert de Pagter",
1852 | "email": "BackEndTea@gmail.com"
1853 | },
1854 | {
1855 | "name": "Symfony Community",
1856 | "homepage": "https://symfony.com/contributors"
1857 | }
1858 | ],
1859 | "description": "Symfony polyfill for ctype functions",
1860 | "homepage": "https://symfony.com",
1861 | "keywords": [
1862 | "compatibility",
1863 | "ctype",
1864 | "polyfill",
1865 | "portable"
1866 | ],
1867 | "support": {
1868 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0"
1869 | },
1870 | "funding": [
1871 | {
1872 | "url": "https://symfony.com/sponsor",
1873 | "type": "custom"
1874 | },
1875 | {
1876 | "url": "https://github.com/fabpot",
1877 | "type": "github"
1878 | },
1879 | {
1880 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1881 | "type": "tidelift"
1882 | }
1883 | ],
1884 | "time": "2020-10-23T09:01:57+00:00"
1885 | },
1886 | {
1887 | "name": "symfony/polyfill-mbstring",
1888 | "version": "v1.1.0",
1889 | "source": {
1890 | "type": "git",
1891 | "url": "https://github.com/symfony/polyfill-mbstring.git",
1892 | "reference": "1289d16209491b584839022f29257ad859b8532d"
1893 | },
1894 | "dist": {
1895 | "type": "zip",
1896 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d",
1897 | "reference": "1289d16209491b584839022f29257ad859b8532d",
1898 | "shasum": ""
1899 | },
1900 | "require": {
1901 | "php": ">=5.3.3"
1902 | },
1903 | "suggest": {
1904 | "ext-mbstring": "For best performance"
1905 | },
1906 | "type": "library",
1907 | "extra": {
1908 | "branch-alias": {
1909 | "dev-master": "1.1-dev"
1910 | }
1911 | },
1912 | "autoload": {
1913 | "psr-4": {
1914 | "Symfony\\Polyfill\\Mbstring\\": ""
1915 | },
1916 | "files": [
1917 | "bootstrap.php"
1918 | ]
1919 | },
1920 | "notification-url": "https://packagist.org/downloads/",
1921 | "license": [
1922 | "MIT"
1923 | ],
1924 | "authors": [
1925 | {
1926 | "name": "Nicolas Grekas",
1927 | "email": "p@tchwork.com"
1928 | },
1929 | {
1930 | "name": "Symfony Community",
1931 | "homepage": "https://symfony.com/contributors"
1932 | }
1933 | ],
1934 | "description": "Symfony polyfill for the Mbstring extension",
1935 | "homepage": "https://symfony.com",
1936 | "keywords": [
1937 | "compatibility",
1938 | "mbstring",
1939 | "polyfill",
1940 | "portable",
1941 | "shim"
1942 | ],
1943 | "time": "2016-01-20T09:13:37+00:00"
1944 | },
1945 | {
1946 | "name": "symfony/stopwatch",
1947 | "version": "v3.0.2",
1948 | "source": {
1949 | "type": "git",
1950 | "url": "https://github.com/symfony/stopwatch.git",
1951 | "reference": "4a204804952ff267ace88cf499e0b4bb302a475e"
1952 | },
1953 | "dist": {
1954 | "type": "zip",
1955 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4a204804952ff267ace88cf499e0b4bb302a475e",
1956 | "reference": "4a204804952ff267ace88cf499e0b4bb302a475e",
1957 | "shasum": ""
1958 | },
1959 | "require": {
1960 | "php": ">=5.5.9"
1961 | },
1962 | "type": "library",
1963 | "extra": {
1964 | "branch-alias": {
1965 | "dev-master": "3.0-dev"
1966 | }
1967 | },
1968 | "autoload": {
1969 | "psr-4": {
1970 | "Symfony\\Component\\Stopwatch\\": ""
1971 | },
1972 | "exclude-from-classmap": [
1973 | "/Tests/"
1974 | ]
1975 | },
1976 | "notification-url": "https://packagist.org/downloads/",
1977 | "license": [
1978 | "MIT"
1979 | ],
1980 | "authors": [
1981 | {
1982 | "name": "Fabien Potencier",
1983 | "email": "fabien@symfony.com"
1984 | },
1985 | {
1986 | "name": "Symfony Community",
1987 | "homepage": "https://symfony.com/contributors"
1988 | }
1989 | ],
1990 | "description": "Symfony Stopwatch Component",
1991 | "homepage": "https://symfony.com",
1992 | "time": "2016-01-03T15:35:16+00:00"
1993 | },
1994 | {
1995 | "name": "symfony/yaml",
1996 | "version": "v3.3.6",
1997 | "source": {
1998 | "type": "git",
1999 | "url": "https://github.com/symfony/yaml.git",
2000 | "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed"
2001 | },
2002 | "dist": {
2003 | "type": "zip",
2004 | "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed",
2005 | "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed",
2006 | "shasum": ""
2007 | },
2008 | "require": {
2009 | "php": ">=5.5.9"
2010 | },
2011 | "require-dev": {
2012 | "symfony/console": "~2.8|~3.0"
2013 | },
2014 | "suggest": {
2015 | "symfony/console": "For validating YAML files using the lint command"
2016 | },
2017 | "type": "library",
2018 | "extra": {
2019 | "branch-alias": {
2020 | "dev-master": "3.3-dev"
2021 | }
2022 | },
2023 | "autoload": {
2024 | "psr-4": {
2025 | "Symfony\\Component\\Yaml\\": ""
2026 | },
2027 | "exclude-from-classmap": [
2028 | "/Tests/"
2029 | ]
2030 | },
2031 | "notification-url": "https://packagist.org/downloads/",
2032 | "license": [
2033 | "MIT"
2034 | ],
2035 | "authors": [
2036 | {
2037 | "name": "Fabien Potencier",
2038 | "email": "fabien@symfony.com"
2039 | },
2040 | {
2041 | "name": "Symfony Community",
2042 | "homepage": "https://symfony.com/contributors"
2043 | }
2044 | ],
2045 | "description": "Symfony Yaml Component",
2046 | "homepage": "https://symfony.com",
2047 | "support": {
2048 | "source": "https://github.com/symfony/yaml/tree/3.3"
2049 | },
2050 | "time": "2017-07-23T12:43:26+00:00"
2051 | },
2052 | {
2053 | "name": "webmozart/assert",
2054 | "version": "1.9.1",
2055 | "source": {
2056 | "type": "git",
2057 | "url": "https://github.com/webmozarts/assert.git",
2058 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389"
2059 | },
2060 | "dist": {
2061 | "type": "zip",
2062 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
2063 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389",
2064 | "shasum": ""
2065 | },
2066 | "require": {
2067 | "php": "^5.3.3 || ^7.0 || ^8.0",
2068 | "symfony/polyfill-ctype": "^1.8"
2069 | },
2070 | "conflict": {
2071 | "phpstan/phpstan": "<0.12.20",
2072 | "vimeo/psalm": "<3.9.1"
2073 | },
2074 | "require-dev": {
2075 | "phpunit/phpunit": "^4.8.36 || ^7.5.13"
2076 | },
2077 | "type": "library",
2078 | "autoload": {
2079 | "psr-4": {
2080 | "Webmozart\\Assert\\": "src/"
2081 | }
2082 | },
2083 | "notification-url": "https://packagist.org/downloads/",
2084 | "license": [
2085 | "MIT"
2086 | ],
2087 | "authors": [
2088 | {
2089 | "name": "Bernhard Schussek",
2090 | "email": "bschussek@gmail.com"
2091 | }
2092 | ],
2093 | "description": "Assertions to validate method input/output with nice error messages.",
2094 | "keywords": [
2095 | "assert",
2096 | "check",
2097 | "validate"
2098 | ],
2099 | "support": {
2100 | "issues": "https://github.com/webmozarts/assert/issues",
2101 | "source": "https://github.com/webmozarts/assert/tree/1.9.1"
2102 | },
2103 | "time": "2020-07-08T17:02:28+00:00"
2104 | }
2105 | ],
2106 | "aliases": [],
2107 | "minimum-stability": "stable",
2108 | "stability-flags": {
2109 | "codeclimate/php-test-reporter": 20
2110 | },
2111 | "prefer-stable": false,
2112 | "prefer-lowest": false,
2113 | "platform": {
2114 | "php": ">=7.0"
2115 | },
2116 | "platform-dev": [],
2117 | "plugin-api-version": "2.3.0"
2118 | }
2119 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Documentation
2 | ## Table of content
3 |
4 | 1. [Requirements](#requirements)
5 | 2. [Installation](#installation)
6 | 3. [What are Cookie Files](#what-are-cookies-file)
7 | 4. [Example](#example)
8 | 5. [Configuration](#configuration)
9 | * [CookieDir](#configuration_cookiedir)
10 | 6. [Cookie File Handler](#cookiefilehandler)
11 | * [Handler Methods](#cookiefilehandler_methods)
12 | 7. [Cookie Jar](#cookie-jar)
13 | * [Jar Methods](#cookie-jar_methods)
14 | 8. [Cookie Entity](#cookie-entity)
15 | 9. [Cookie Collection](#cookie-collection)
16 | * [Importants Facts](#cookie-collection_importants-facts)
17 | * [Collection Methods](#cookie-collection_methods)
18 |
19 | ----------
20 |
21 | ## Requirements
22 | This is library is only available for **PHP7+**
23 | There is no other dependencies
24 |
25 |
26 | ## Installation
27 | This library is available on packagist (**Composer**)
28 | ```shell
29 | composer require kegi/netscape-cookie-file-handler
30 | ```
31 |
32 | ## What are Cookies Files ?
33 | The Netscape cookie files are widely used. Curl, by example, allows you to select a file (called the cookie jar) to save and read the cookies using this format. This library will help you to manipulate and read those cookies.
34 |
35 |
36 | ## Example
37 | Simple example of reading + writing cookies
38 |
39 | ```php
40 | /*Open and parse the cookie file*/
41 |
42 | $configuration = (new Configuration())->setCookieDir('cookies/');
43 | $cookieJar = (new CookieFileHandler($configuration))->parseFile('my_cookie_file');
44 |
45 | /*Add (and save) a cookie*/
46 |
47 | $cookieJar->add(
48 | (new Cookie())
49 | ->setHttpOnly(true)
50 | ->setPath('/foo')
51 | ->setSecure(true)
52 | ->setExpire(new DateTime('2020-02-20 20:20:02'))
53 | ->setName('foo')
54 | ->setValue('bar')
55 | )->persist();
56 | ```
57 |
58 |
59 | ## Configuration
60 | For now, the configurations are pretty easy, there is only one parameter.
61 |
62 |
63 | ### cookieDir
64 | This is where the library will look for cookie files. Note that this parameter is mandatory if you want to manipulate file.
65 | ```
66 | $configuration = new Configuration();
67 | $configuration->setCookieDir('cookies/');
68 | $configuration->getCookieDir(); //return "cookies/"
69 | ```
70 |
71 |
72 | ## Cookie File Handler
73 | This is the main library class (**CookieFileHandler**) and it implements **CookieFileHandlerInterface**. This class can receive a configuration object (**ConfigurationInterface**) and will allows you to get a cookie jar (**CookieJarInterface**).
74 |
75 |
76 | ### Handler Methods
77 |
78 | **parseFile** ( string **$file** )
79 | > Note: Configuration with "**cookieDir**" are needed to use this method. The file name will be searched from **cookieDir**
80 | > Note: The cookie jar will be associated with this file, **you will be able to persist changes to that file**.
81 |
82 | **parseContent** ( string **$content** )
83 | > This will return a cookie collection.
84 |
85 | ### Exceptions
86 |
87 | Those exceptions can be thrown when using the cookie jar :
88 |
89 | **NetscapeCookieFileHandlerException**
90 | > Illegal operation, eg. missing configuration
91 |
92 | **ParserException**
93 | > Error reading the cookie file
94 |
95 |
96 | ## Cookie Jar
97 | A Cookie Jar (**CookieJar**) implements "**CookieJarInterface**" and contains a collection of cookies (**CookieCollectionInterface**). A cookie jar is associated to a file. All changes applied to the cookies can be persisted using the **persist()** function.
98 |
99 | The following collection methods are availables :
100 |
101 | - get
102 | - getAll
103 | - add
104 | - has
105 | - delete
106 | - deleteAll
107 |
108 |
109 | Those exceptions can be thrown when using the cookie jar :
110 |
111 | **CookieJarException**
112 | > Cookie Jar illegal operations
113 |
114 | **PersisterException**
115 | > Errors when saving the cookie file
116 |
117 |
118 | ### Cookie Jar Methods
119 |
120 | **getCookiesFile** ()
121 | > To get the cookies file (to persist the cookies)
122 |
123 | **setCookiesFile** ( string **$cookiesFile** )
124 | > To set the cookies file (will be append to **cookieDir** from the configuration)
125 |
126 | **persist** ()
127 | > This method will save the current cookie collection in the cookies file
128 |
129 |
130 | ## Cookie Entity
131 | All cookies are hold inside a "**Cookie**" object and implements "**CookieInterface**", "**CookieInterface**" extends "**JsonSerializable**" which allows you to directly convert it with "**json_encode**"..
132 |
133 | | Parameter | Default | Description
134 | | --- | --- | ---
135 | | domain | NULL | Domain where the cookie is active
136 | | httpOnly | false | If set to true, the cookie will only be enabled for http requests
137 | | flag | true | If enable, all machines within a given domain can access the variable
138 | | path | / | Inside the domain, this cookie will only be available for this path
139 | | secure | false | If enable, this cookie will only be active with HTTPS requests
140 | | expire | NULL | Expiration of the cookie. DateTime object or NULL if no expiration date
141 | | name | | Name of the cookie (Mandatory) |
142 | | value | | Value of the cookie (Empty value cookie will be discarded) |
143 |
144 | You can access cookie data using getters and setters.
145 |
146 |
147 |
148 | ## Cookie Collection
149 | A collection of cookies is stored inside a "**CookieCollection**" and implements "**CookieCollectionInterface**". "**CookieCollectionInterface**" extends "**JsonSerializable**" which allows you to directly convert it with "**json_encode**".
150 |
151 |
152 | ### Importants Facts
153 | - The cookies are ordered by domain
154 | - The cookie (name) are unique by domain
155 | - A cookie with empty value will be ignored
156 |
157 |
158 | ### Collection Methods
159 |
160 | **getCookies** ()
161 | > This method return the array of cookies ordered by domain and cookie name. This should be used as debugging purpose only. Use get() or getAll() instead to receive a collection of cookies.
162 | > ```
163 | > ['domain1.dev'] =>
164 | > ['cookie_a'] => ...
165 | > ['cookie_b'] => ...
166 | > ['domain2.dev'] =>
167 | > ['cookie_a'] => ...
168 | > ```
169 |
170 |
171 | **setCookies** (array **$cookies**)
172 | > This methods set the array of cookies. SetCookie will clear all cookies, perform some tests on array items and will internally call **add()**. Please note that **all cookies need to have a name and a domain** or an exception (**CookieCollectionException**) will be thrown. You can also send your cookies to the constructor when creating a new collection.
173 |
174 |
175 | **get** ( string **$cookieName**, string **$domain** = null )
176 | > This will find the cookie by name on the given domain. If no domain is specified, the collection will search inside all domains. This will return a "**CookieInterface**" object or **Null** if nothing is found.
177 |
178 |
179 | **getAll** ( string **$domain** = null )
180 | > This will find all cookies of a given domain or all cookies if no domain is specified. This will always return a "**CookieCollectionInterface**" object.
181 |
182 |
183 | **add** ( cookieInterface **$cookie** )
184 | > This will add a cookie to the collection. NOTES :
185 | > - If the given cookie has no domain, **the cookie will be added to ALL domains** that are already inside the collection. If there is no existing cookies, an exception (**CookieCollectionException**) will be thrown.
186 | > - If you add an existing cookie, you will override it.
187 |
188 |
189 | **has** ( string **$cookieName**, string **$domain** = null )
190 | > This will return true if the cookie exists for the given domain (if specified, or in all domains). Please note that cookies with empty value are discarded.
191 |
192 |
193 | **delete** ( string **$cookieName**, string **$domain** = null )
194 | > This will remove a cookie from the collection for the given domain or in all domains if $domain is not set.
195 |
196 |
197 | **deleteAll** ( string **$domain** = null )
198 | > This will remove all cookies of the given domain or all cookies in the collection if $domain is not set.
199 |
--------------------------------------------------------------------------------
/examples/edit_file.php:
--------------------------------------------------------------------------------
1 | setCookieDir(Example::COOKIES_DIR);
24 | $cookieJar
25 | = (new CookieFileHandler($configuration))->parseFile(Example::EXAMPLE_COPY_FILE_NAME);
26 | $nbCookies = Example::countCookies($cookieJar->getAll()->toArray());
27 |
28 | $cookieJar->add(
29 | (new Cookie())
30 | ->setHttpOnly(true)
31 | ->setPath('/foo')
32 | ->setSecure(true)
33 | ->setExpire(new DateTime('2020-02-20 20:20:02'))
34 | ->setName('foo')
35 | ->setValue('bar')
36 | )->persist();
37 |
38 | /*Because we injected a cookie with no domain, this cookie has been added to
39 | all domains inside the cookie file*/
40 |
41 | echo 'Cookie file edited successfully !' . PHP_EOL;
42 |
43 | echo sprintf(
44 | 'There were %1$d cookie(s) and now, there are %2$d cookie(s)',
45 | $nbCookies,
46 | Example::countCookies($cookieJar->getAll()->toArray())
47 | ) . PHP_EOL;
48 |
49 | echo sprintf(
50 | 'Compare %1$s and %2$s',
51 | Example::EXAMPLE_FILE_NAME,
52 | Example::EXAMPLE_COPY_FILE_NAME
53 | ) . PHP_EOL . PHP_EOL;
54 | } catch (NetscapeCookieFileHandlerException $e) {
55 | echo 'Handler Exception :' . PHP_EOL . PHP_EOL;
56 | echo $e->getMessage();
57 | } catch (Exception $e) {
58 | echo 'An exception occured :' . PHP_EOL . PHP_EOL;
59 | echo $e->getMessage();
60 | }
61 |
--------------------------------------------------------------------------------
/examples/includes/Example.php:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | ./tests/NetscapeCookieFileHandler/
13 |
14 |
15 |
16 |
17 |
18 | ./src/NetscapeCookieFileHandler/
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Configuration/Configuration.php:
--------------------------------------------------------------------------------
1 | cookieDir;
19 | }
20 |
21 | /**
22 | * @param string $cookieDir
23 | *
24 | * @return ConfigurationInterface
25 | */
26 | public function setCookieDir(string $cookieDir) : ConfigurationInterface
27 | {
28 | $this->cookieDir = $cookieDir;
29 |
30 | return $this;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Configuration/ConfigurationInterface.php:
--------------------------------------------------------------------------------
1 | configuration;
19 | }
20 |
21 | /**
22 | * @param ConfigurationInterface|null $configuration
23 | *
24 | * @return $this
25 | */
26 | public function setConfiguration(
27 | ConfigurationInterface $configuration = null
28 | ) {
29 | $this->configuration = $configuration;
30 |
31 | return $this;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Configuration/HasConfigurationInterface.php:
--------------------------------------------------------------------------------
1 | configuration;
19 | }
20 |
21 | /**
22 | * @param ConfigurationInterface $configuration
23 | *
24 | * @return $this
25 | */
26 | public function setConfiguration(ConfigurationInterface $configuration
27 | ) {
28 | $this->configuration = $configuration;
29 |
30 | return $this;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Cookie/Cookie.php:
--------------------------------------------------------------------------------
1 | domain;
56 | }
57 |
58 | /**
59 | * @param string|null $domain
60 | *
61 | * @return CookieInterface
62 | */
63 | public function setDomain(string $domain = null) : CookieInterface
64 | {
65 | $this->domain = $domain;
66 |
67 | return $this;
68 | }
69 |
70 | /**
71 | * @return bool
72 | */
73 | public function isHttpOnly() : bool
74 | {
75 | return $this->httpOnly;
76 | }
77 |
78 | /**
79 | * @param bool $httpOnly
80 | *
81 | * @return CookieInterface
82 | */
83 | public function setHttpOnly(bool $httpOnly) : CookieInterface
84 | {
85 | $this->httpOnly = $httpOnly;
86 |
87 | return $this;
88 | }
89 |
90 | /**
91 | * @return bool
92 | */
93 | public function isFlag() : bool
94 | {
95 | return $this->flag;
96 | }
97 |
98 | /**
99 | * @param bool $flag
100 | *
101 | * @return CookieInterface
102 | */
103 | public function setFlag(bool $flag) : CookieInterface
104 | {
105 | $this->flag = $flag;
106 |
107 | return $this;
108 | }
109 |
110 | /**
111 | * @return string
112 | */
113 | public function getPath() : string
114 | {
115 | return $this->path;
116 | }
117 |
118 | /**
119 | * @param string $path
120 | *
121 | * @return CookieInterface
122 | */
123 | public function setPath(string $path) : CookieInterface
124 | {
125 | $this->path = $path;
126 |
127 | return $this;
128 | }
129 |
130 | /**
131 | * @return bool
132 | */
133 | public function isSecure() : bool
134 | {
135 | return $this->secure;
136 | }
137 |
138 | /**
139 | * @param bool $secure
140 | *
141 | * @return CookieInterface
142 | */
143 | public function setSecure(bool $secure) : CookieInterface
144 | {
145 | $this->secure = $secure;
146 |
147 | return $this;
148 | }
149 |
150 | /**
151 | * @return DateTime|null
152 | */
153 | public function getExpire()
154 | {
155 | return $this->expire;
156 | }
157 |
158 | /**
159 | * @param DateTime|null $expire
160 | *
161 | * @return CookieInterface
162 | */
163 | public function setExpire($expire) : CookieInterface
164 | {
165 | $this->expire = $expire;
166 |
167 | return $this;
168 | }
169 |
170 | /**
171 | * @return string
172 | */
173 | public function getName() : string
174 | {
175 | return $this->name;
176 | }
177 |
178 | /**
179 | * @param string $name
180 | *
181 | * @return CookieInterface
182 | */
183 | public function setName(string $name) : CookieInterface
184 | {
185 | $this->name = $name;
186 |
187 | return $this;
188 | }
189 |
190 | /**
191 | * @return string
192 | */
193 | public function getValue() : string
194 | {
195 | return $this->value;
196 | }
197 |
198 | /**
199 | * @param string $value
200 | *
201 | * @return CookieInterface
202 | */
203 | public function setValue(string $value) : CookieInterface
204 | {
205 | $this->value = $value;
206 |
207 | return $this;
208 | }
209 |
210 | /**
211 | * @return array
212 | */
213 | public function toArray() : array
214 | {
215 | return [
216 | 'domain' => $this->getDomain(),
217 | 'httpOnly' => $this->isHttpOnly(),
218 | 'flag' => $this->isFlag(),
219 | 'path' => $this->getPath(),
220 | 'secure' => $this->isSecure(),
221 | 'expire' => $this->getExpire(),
222 | 'name' => $this->getName(),
223 | 'value' => $this->getValue(),
224 | ];
225 | }
226 |
227 | /**
228 | * @return array
229 | */
230 | public function jsonSerialize() : array
231 | {
232 | return $this->toArray();
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Cookie/CookieCollection.php:
--------------------------------------------------------------------------------
1 | setCookies($cookies);
22 | }
23 | }
24 |
25 | /**
26 | * @return array
27 | */
28 | public function getCookies()
29 | {
30 | return $this->cookies;
31 | }
32 |
33 | /**
34 | * @param array $cookies
35 | *
36 | * @return CookieCollectionInterface
37 | * @throws CookieCollectionException
38 | */
39 | public function setCookies(array $cookies) : CookieCollectionInterface
40 | {
41 | $this->cookies = [];
42 |
43 | foreach ($cookies as $cookie) {
44 | if (!is_object($cookie)) {
45 | throw new CookieCollectionException(
46 | sprintf(
47 | 'Expected CookieInterface object, got : %1$s',
48 | gettype($cookie)
49 | )
50 | );
51 | }
52 |
53 | if (!($cookie instanceof CookieInterface)) {
54 | throw new CookieCollectionException(
55 | sprintf(
56 | 'Expected CookieInterface, got : %1$s',
57 | get_class($cookie)
58 | )
59 | );
60 | }
61 |
62 | if (empty($cookie->getDomain())) {
63 | throw new CookieCollectionException(
64 | 'You can\'t have a cookie with no domain when using setCookies'
65 | );
66 | }
67 |
68 | if (empty($cookie->getName())) {
69 | throw new CookieCollectionException(
70 | 'You can\'t have a cookie with no name'
71 | );
72 | }
73 |
74 | if (empty($cookie->getValue())) {
75 | continue;
76 | }
77 |
78 | $this->add($cookie);
79 | }
80 |
81 | return $this;
82 | }
83 |
84 | /**
85 | * @param string $cookieName
86 | * @param string|null $domain
87 | *
88 | * @return CookieInterface|null
89 | */
90 | public function get(string $cookieName, string $domain = null)
91 | {
92 | if ($domain === null) {
93 |
94 | /*find the first occurence on any domain*/
95 |
96 | foreach ($this->cookies as $cookies) {
97 | if (isset($cookies[$cookieName])) {
98 | return $cookies[$cookieName];
99 | }
100 | }
101 |
102 | return null;
103 | } else {
104 | return $this->cookies[$domain][$cookieName] ?? null;
105 | }
106 | }
107 |
108 | /**
109 | * @param string|null $domain
110 | *
111 | * @return CookieCollectionInterface
112 | */
113 | public function getAll(string $domain = null) : CookieCollectionInterface
114 | {
115 | if ($domain === null) {
116 | return $this;
117 | } else {
118 | $collection = new CookieCollection();
119 |
120 | if (isset($this->cookies[$domain])) {
121 | foreach ($this->cookies[$domain] as $cookie) {
122 | $collection->add($cookie);
123 | }
124 | }
125 |
126 | return $collection;
127 | }
128 | }
129 |
130 | /**
131 | * @param CookieInterface $cookie
132 | *
133 | * @return CookieCollectionInterface
134 | * @throws CookieCollectionException
135 | */
136 | public function add(
137 | CookieInterface $cookie
138 | ) : CookieCollectionInterface {
139 | $cookieDomain = $cookie->getDomain();
140 | $cookieName = $cookie->getName();
141 |
142 | if ($cookieDomain === null) {
143 |
144 | /*if there is no cookie and the given cookie doesn't have a domain,
145 | we throw an exception*/
146 |
147 | if (count($this->cookies) === 0) {
148 | throw new CookieCollectionException(
149 | 'You cannot add a cookie with no domain to an empty cookie jar'
150 | );
151 | }
152 |
153 | /*we add this cookie to all knowns domains*/
154 |
155 | foreach ($this->cookies as $domain => $cookies) {
156 | $generatedCookie = clone $cookie;
157 | $generatedCookie->setDomain($domain);
158 | $this->cookies[$domain][$cookieName] = $generatedCookie;
159 | }
160 | } else {
161 | if (!isset($this->cookies[$cookieDomain])) {
162 | $this->cookies[$cookieDomain] = [];
163 | }
164 |
165 | $this->cookies[$cookieDomain][$cookieName] = $cookie;
166 | }
167 |
168 | return $this;
169 | }
170 |
171 | /**
172 | * @param string $cookieName
173 | * @param string|null $domain
174 | *
175 | * @return bool
176 | */
177 | public function has(string $cookieName, string $domain = null) : bool
178 | {
179 | if ($domain === null) {
180 |
181 | /*find this cookie for all domains*/
182 |
183 | foreach ($this->cookies as $cookies) {
184 | if (isset($cookies[$cookieName])) {
185 | return true;
186 | }
187 | }
188 |
189 | return false;
190 | }
191 |
192 | return isset($this->cookies[$domain])
193 | && isset($this->cookies[$domain][$cookieName]);
194 | }
195 |
196 | /**
197 | * @param string $cookieName
198 | * @param string|null $domain
199 | *
200 | * @return CookieCollectionInterface
201 | */
202 | public function delete(
203 | string $cookieName,
204 | string $domain = null
205 | ) : CookieCollectionInterface {
206 | if ($domain === null) {
207 |
208 | /*delete this cookie for all domains*/
209 |
210 | foreach ($this->cookies as $cookieDomain => $cookies) {
211 | if (isset($cookies[$cookieName])) {
212 | unset($this->cookies[$cookieDomain][$cookieName]);
213 | }
214 |
215 | if (empty($this->cookies[$cookieDomain])) {
216 | unset($this->cookies[$cookieDomain]);
217 | }
218 | }
219 | } else {
220 | if (isset($this->cookies[$domain][$cookieName])) {
221 | unset($this->cookies[$domain][$cookieName]);
222 |
223 | if (empty($this->cookies[$domain])) {
224 | unset($this->cookies[$domain]);
225 | }
226 | }
227 | }
228 |
229 | return $this;
230 | }
231 |
232 | /**
233 | * @param string|null $domain
234 | *
235 | * @return CookieCollectionInterface
236 | */
237 | public function deleteAll(string $domain = null) : CookieCollectionInterface
238 | {
239 | if ($domain === null) {
240 | $this->cookies = [];
241 | } else {
242 | if (isset($this->cookies[$domain])) {
243 | unset($this->cookies[$domain]);
244 | }
245 | }
246 |
247 | return $this;
248 | }
249 |
250 | /**
251 | * @return array
252 | */
253 | public function toArray() : array
254 | {
255 | $output = [];
256 |
257 | foreach ($this->cookies as $domain => $cookies) {
258 | $output[$domain] = [];
259 |
260 | foreach ($cookies as $cookieName => $cookie) {
261 |
262 | /** @var CookieInterface $cookie */
263 |
264 | $output[$domain][$cookieName] = $cookie->toArray();
265 | }
266 | }
267 |
268 | return $output;
269 | }
270 |
271 | /**
272 | * @return array
273 | */
274 | public function jsonSerialize() : array
275 | {
276 | return $this->toArray();
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Cookie/CookieCollectionInterface.php:
--------------------------------------------------------------------------------
1 | setConfiguration($configuration);
32 | }
33 |
34 | /**
35 | * @param string $file
36 | *
37 | * @return CookieJarInterface
38 | * @throws NetscapeCookieFileHandlerException
39 | */
40 | public function parseFile(string $file) : CookieJarInterface
41 | {
42 | if (!($this->getConfiguration() instanceof ConfigurationInterface)) {
43 | throw new NetscapeCookieFileHandlerException(
44 | 'Configuration is mandatory with parseFile method'
45 | );
46 | }
47 |
48 | return new CookieJar(
49 | $this->getParser()->parseFile($file),
50 | $this->getConfiguration(),
51 | $file
52 | );
53 | }
54 |
55 | /**
56 | * @param string $content
57 | *
58 | * @return CookieCollectionInterface
59 | */
60 | public function parseContent(string $content) : CookieCollectionInterface
61 | {
62 | return $this->getParser()->parseContent($content);
63 | }
64 |
65 | /**
66 | * @return ParserInterface
67 | */
68 | public function getParser() : ParserInterface
69 | {
70 | return $this->parser ?? new Parser($this->getConfiguration());
71 | }
72 |
73 | /**
74 | * @codeCoverageIgnore
75 | *
76 | * @param ParserInterface $parser
77 | *
78 | * @return CookieFileHandlerInterface
79 | */
80 | public function setParser(ParserInterface $parser
81 | ) : CookieFileHandlerInterface {
82 | $this->parser = $parser;
83 |
84 | return $this;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/CookieFileHandlerInterface.php:
--------------------------------------------------------------------------------
1 | setConfiguration($configuration);
44 | $this->setCookies($cookies);
45 | $this->setCookiesFile($cookiesFile);
46 | }
47 |
48 | /**
49 | * @return CookieCollectionInterface
50 | */
51 | public function getCookies() : CookieCollectionInterface
52 | {
53 | return $this->cookies;
54 | }
55 |
56 | /**
57 | * @param CookieCollectionInterface $cookies
58 | *
59 | * @return CookieJarInterface
60 | */
61 | public function setCookies(CookieCollectionInterface $cookies
62 | ) : CookieJarInterface {
63 | $this->cookies = $cookies;
64 |
65 | return $this;
66 | }
67 |
68 | /**
69 | * @return string
70 | */
71 | public function getCookiesFile() : string
72 | {
73 | return $this->cookiesFile;
74 | }
75 |
76 | /**
77 | * @param string $cookiesFile
78 | *
79 | * @return CookieJarInterface
80 | */
81 | public function setCookiesFile(string $cookiesFile) : CookieJarInterface
82 | {
83 | $this->cookiesFile = $cookiesFile;
84 |
85 | return $this;
86 | }
87 |
88 | /**
89 | * @param string $cookieName
90 | * @param string|null $domain
91 | *
92 | * @return CookieInterface|null
93 | */
94 | public function get(string $cookieName, string $domain = null)
95 | {
96 | return $this->getCookies()->get($cookieName, $domain);
97 | }
98 |
99 | /**
100 | * @param string|null $domain
101 | *
102 | * @return CookieCollectionInterface
103 | */
104 | public function getAll(string $domain = null) : CookieCollectionInterface
105 | {
106 | return $this->getCookies()->getAll($domain);
107 | }
108 |
109 | /**
110 | * @param CookieInterface $cookie
111 | *
112 | * @return CookieJarInterface
113 | */
114 | public function add(
115 | CookieInterface $cookie
116 | ) : CookieJarInterface {
117 | $this->getCookies()->add($cookie);
118 |
119 | return $this;
120 | }
121 |
122 | /**
123 | * @param string $cookieName
124 | * @param string|null $domain
125 | *
126 | * @return bool
127 | */
128 | public function has(string $cookieName, string $domain = null) : bool
129 | {
130 | return $this->getCookies()->has($cookieName, $domain);
131 | }
132 |
133 | /**
134 | * @param string $cookieName
135 | * @param string|null $domain
136 | *
137 | * @return CookieJarInterface
138 | */
139 | public function delete(
140 | string $cookieName,
141 | string $domain = null
142 | ) : CookieJarInterface {
143 | $this->getCookies()->delete($cookieName);
144 |
145 | return $this;
146 | }
147 |
148 | /**
149 | * @param string|null $domain
150 | *
151 | * @return CookieJarInterface
152 | */
153 | public function deleteAll(string $domain = null) : CookieJarInterface
154 | {
155 | $this->getCookies()->deleteAll($domain);
156 |
157 | return $this;
158 | }
159 |
160 | /**
161 | * @return CookieJarInterface
162 | * @throws CookieJarException
163 | */
164 | public function persist() : CookieJarInterface
165 | {
166 | $this->getPersister()
167 | ->persist($this->getCookies(), $this->getCookiesFile());
168 |
169 | return $this;
170 | }
171 |
172 | /**
173 | * @return PersisterInterface
174 | */
175 | public function getPersister() : PersisterInterface
176 | {
177 | return $this->persister ??
178 | new Persister($this->getConfiguration());
179 | }
180 |
181 | /**
182 | * @codeCoverageIgnore
183 | *
184 | * @param PersisterInterface $persister
185 | *
186 | * @return CookieJarInterface
187 | */
188 | public function setPersister(PersisterInterface $persister
189 | ) : CookieJarInterface {
190 | $this->persister = $persister;
191 |
192 | return $this;
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Jar/CookieJarInterface.php:
--------------------------------------------------------------------------------
1 | setConfiguration($configuration);
29 | }
30 |
31 | /**
32 | * @param string $file
33 | *
34 | * @return CookieCollectionInterface
35 | * @throws ParserException
36 | */
37 | public function parseFile(string $file) : CookieCollectionInterface
38 | {
39 | if (!($this->getConfiguration() instanceof ConfigurationInterface)) {
40 | throw new ParserException(
41 | 'You need to inject configurations in order to parse a file'
42 | );
43 | }
44 |
45 | if (empty($this->getConfiguration()->getCookieDir())) {
46 | throw new ParserException(
47 | 'You need to specify the cookieDir parameter in configurations in order to parse a file'
48 | );
49 | }
50 |
51 | $cookieDir = rtrim(
52 | $this->getConfiguration()->getCookieDir(),
53 | DIRECTORY_SEPARATOR
54 | ) . DIRECTORY_SEPARATOR;
55 |
56 | $file = $cookieDir . $file;
57 |
58 | if (!is_file($file)) {
59 | throw new ParserException(
60 | sprintf(
61 | 'File not found : %1$s',
62 | $file
63 | )
64 | );
65 | }
66 |
67 | $fileContent = file_get_contents($file);
68 |
69 | // @codeCoverageIgnoreStart
70 |
71 | if ($fileContent === false) {
72 | throw new ParserException(
73 | sprintf(
74 | 'Unable to read file : %1$s',
75 | $file
76 | )
77 | );
78 | }
79 |
80 | // @codeCoverageIgnoreEnd
81 |
82 | return $this->parseContent($fileContent);
83 | }
84 |
85 | /**
86 | * @param string $filecontent
87 | *
88 | * @return CookieCollectionInterface
89 | */
90 | public function parseContent(string $filecontent
91 | ) : CookieCollectionInterface {
92 | $cookies = new CookieCollection();
93 |
94 | foreach (explode("\n", $filecontent) as $line) {
95 | $line = trim($line);
96 | $cookieData = array_map('trim', explode("\t", $line, 7));
97 |
98 | if (count($cookieData) !== 7) {
99 | continue;
100 | }
101 |
102 | $httpOnly = false;
103 | $httpOnlyPrefixLength = strlen(self::HTTP_ONLY_PREFIX);
104 |
105 | if (substr($cookieData[0], 0, $httpOnlyPrefixLength)
106 | === self::HTTP_ONLY_PREFIX
107 | ) {
108 | $cookieData[0] = substr($cookieData[0], $httpOnlyPrefixLength);
109 | $httpOnly = true;
110 | } else {
111 | if ($cookieData[0][0] === '#') {
112 | continue;
113 | }
114 | }
115 |
116 | $expire = empty($cookieData[4]) ? null : $cookieData[4];
117 |
118 | if (preg_match('#^[0-9]+$#i', $expire)) {
119 | $expire = new DateTime(date('Y-m-d H:i:s', (int)$expire));
120 | }
121 |
122 | $cookies->add(
123 | (new Cookie())
124 | ->setDomain($cookieData[0])
125 | ->setHttpOnly($httpOnly)
126 | ->setFlag(strtolower($cookieData[1]) === 'true')
127 | ->setPath($cookieData[2])
128 | ->setSecure(strtolower($cookieData[3]) === 'true')
129 | ->setExpire($expire)
130 | ->setName($cookieData[5])
131 | ->setValue($cookieData[6])
132 | );
133 | }
134 |
135 | return $cookies;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Parser/ParserInterface.php:
--------------------------------------------------------------------------------
1 | setConfiguration($configuration);
36 | }
37 |
38 | /**
39 | * @param CookieCollectionInterface $cookies
40 | * @param string $filename
41 | *
42 | * @return PersisterInterface
43 | * @throws PersisterException
44 | * @throws ParserException
45 | */
46 | public function persist(
47 | CookieCollectionInterface $cookies,
48 | string $filename
49 | ) : PersisterInterface {
50 | if (empty($this->getConfiguration()->getCookieDir())) {
51 | throw new PersisterException(
52 | 'You need to specify the cookieDir parameter in configurations in order to persist a file'
53 | );
54 | }
55 |
56 | $cookieDir = rtrim(
57 | $this->getConfiguration()->getCookieDir(),
58 | DIRECTORY_SEPARATOR
59 | ) . DIRECTORY_SEPARATOR;
60 |
61 | $filename = $cookieDir . $filename;
62 |
63 | $fileContent = $this->generateFileOutput($cookies);
64 |
65 | // @codeCoverageIgnoreStart
66 |
67 | if (empty($fileContent)) {
68 | if (is_file($filename)) {
69 | if (!unlink($filename)) {
70 | throw new PersisterException(
71 | sprintf(
72 | 'Unable to delete the cookies file : %1$s',
73 | $filename
74 | )
75 | );
76 | }
77 | }
78 | } else {
79 | if (file_put_contents($filename, $fileContent) === false) {
80 | if (file_exists($filename)) {
81 | throw new PersisterException(
82 | sprintf(
83 | 'Unable to edit the cookies file : %1$s',
84 | $filename
85 | )
86 | );
87 | } else {
88 | throw new PersisterException(
89 | sprintf(
90 | 'Unable to create the cookies file : %1$s',
91 | $filename
92 | )
93 | );
94 | }
95 | }
96 | }
97 |
98 | // @codeCoverageIgnoreEnd
99 |
100 | return $this;
101 | }
102 |
103 | /**
104 | * Returns the cookies file content or false if any cookies
105 | *
106 | * @param CookieCollectionInterface $cookies
107 | *
108 | * @return string|bool
109 | */
110 | private function generateFileOutput(
111 | CookieCollectionInterface $cookies
112 | ) {
113 | $output = '';
114 |
115 | foreach ($cookies->getCookies() as $domainCookies) {
116 | foreach ($domainCookies as $cookie) {
117 |
118 | /** @var CookieInterface $cookie */
119 |
120 | $domain = $cookie->getDomain();
121 | $httpOnly = $cookie->isHttpOnly();
122 | $flag = $cookie->isFlag();
123 | $path = $cookie->getPath();
124 | $secure = $cookie->isSecure();
125 | $expire = $cookie->getExpire();
126 | $name = $cookie->getName();
127 | $value = $cookie->getValue();
128 |
129 | /*format data for output*/
130 |
131 | if ($httpOnly) {
132 | $domain = Parser::HTTP_ONLY_PREFIX . $domain;
133 | }
134 |
135 | $flag = $flag ? 'TRUE' : 'FALSE';
136 | $secure = $secure ? 'TRUE' : 'FALSE';
137 |
138 | if (empty($path)) {
139 | $path = '/';
140 | }
141 |
142 | if ($expire instanceof DateTime) {
143 | $expire = (string)$expire->getTimestamp();
144 | } else {
145 | $expire = '0';
146 | }
147 |
148 | /*add cookie to file*/
149 |
150 | $output .= implode("\t", array_map('trim', [
151 | $domain,
152 | $flag,
153 | $path,
154 | $secure,
155 | $expire,
156 | $name,
157 | $value,
158 | ])) . PHP_EOL;
159 | }
160 | }
161 |
162 | if (empty($output)) {
163 | return false;
164 | }
165 |
166 | return implode(PHP_EOL, array_map(function ($line) {
167 | return '# ' . $line;
168 | }, self::FILE_HEADERS)) . PHP_EOL . PHP_EOL . $output;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/NetscapeCookieFileHandler/Persister/PersisterInterface.php:
--------------------------------------------------------------------------------
1 | assertTrue(
17 | ($configuration instanceof ConfigurationInterface),
18 | 'Configuration class need to implement ConfigurationInterface'
19 | );
20 | }
21 |
22 | public function testCookieDirParameterTest()
23 | {
24 | $dir = 'foo';
25 |
26 | $configuration = new Configuration();
27 | $configuration->setCookieDir($dir);
28 |
29 | $this->assertEquals(
30 | $dir,
31 | $configuration->getCookieDir()
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/Cookie/CookieCollectionTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(
21 | ($cookieCollection instanceof CookieCollectionInterface),
22 | 'CookieCollection class need to implement CookieCollectionInterface'
23 | );
24 | }
25 |
26 | public function testSetCookies()
27 | {
28 | $cookieCollection = new CookieCollection();
29 | $this->assertEquals([], $cookieCollection->getCookies());
30 |
31 | $cookies = [
32 | (new Cookie())
33 | ->setDomain('foo.bar')
34 | ->setName('foo')
35 | ];
36 |
37 | /** @var CookieInterface[] $cookies */
38 |
39 | $cookieCollection->setCookies($cookies);
40 |
41 | /*we don't expect the cookie because the value was empty*/
42 |
43 | $this->assertEquals([], $cookieCollection->getCookies());
44 |
45 | $cookies[0]->setValue('bar');
46 |
47 | $cookies[] = (new Cookie())
48 | ->setDomain('bar.baz')
49 | ->setName('biz')
50 | ->setValue('boz');
51 |
52 | $cookieCollection->setCookies($cookies);
53 |
54 | /*now, we expect the cookie to be there, plus the new one. Ordered by domain*/
55 |
56 | $cookieReturnes = $cookieCollection->getCookies();
57 |
58 | $this->assertContains($cookies[0],
59 | $cookieReturnes[$cookies[0]->getDomain()]);
60 |
61 | $this->assertContains($cookies[1],
62 | $cookieReturnes[$cookies[1]->getDomain()]);
63 | }
64 |
65 | public function testWrongVariableTypeSetCookie()
66 | {
67 | $this->expectException(CookieCollectionException::class);
68 |
69 | $cookieCollection = new CookieCollection();
70 | $cookieCollection->setCookies([
71 | 'not_supported'
72 | ]);
73 | }
74 |
75 | public function testWrongObjectSetCookie()
76 | {
77 | $this->expectException(CookieCollectionException::class);
78 |
79 | $cookieCollection = new CookieCollection();
80 | $cookieCollection->setCookies([
81 | new stdClass()
82 | ]);
83 | }
84 |
85 | public function testNoDomainSetCookie()
86 | {
87 | $this->expectException(CookieCollectionException::class);
88 |
89 | $cookieCollection = new CookieCollection();
90 | $cookieCollection->setCookies([
91 | (new Cookie())
92 | ->setName('foo')
93 | ]);
94 | }
95 |
96 | public function testNoNameSetCookie()
97 | {
98 | $this->expectException(CookieCollectionException::class);
99 |
100 | $cookieCollection = new CookieCollection();
101 | $cookieCollection->setCookies([
102 | (new Cookie())
103 | ->setDomain('foo.bar')
104 | ]);
105 | }
106 |
107 | public function testGet()
108 | {
109 | $cookie1 = (new Cookie())
110 | ->setDomain('domain1.dev')
111 | ->setName('cookie1')
112 | ->setValue('bar');
113 |
114 | $cookie2 = (new Cookie())
115 | ->setDomain('domain2.dev')
116 | ->setName('cookie1')
117 | ->setValue('baz');
118 |
119 | $cookie3 = (new Cookie())
120 | ->setDomain('domain2.dev')
121 | ->setName('cookie2')
122 | ->setValue('biz');
123 |
124 | $cookieCollection = new CookieCollection([
125 | $cookie1,
126 | $cookie2,
127 | $cookie3
128 | ]);
129 |
130 | $this->assertNull($cookieCollection->get('fake_cookie_name'));
131 |
132 | $this->assertEquals($cookie1, $cookieCollection->get('cookie1'));
133 |
134 | $this->assertEquals($cookie2,
135 | $cookieCollection->get('cookie1', 'domain2.dev'));
136 |
137 | $this->assertEquals($cookie3,
138 | $cookieCollection->get('cookie2', 'domain2.dev'));
139 |
140 | $this->assertEquals($cookieCollection, $cookieCollection->getAll());
141 |
142 | /*getAll tests*/
143 |
144 | $allFakeDomain = $cookieCollection->getAll('fake_domain');
145 |
146 | $this->assertTrue(
147 | ($allFakeDomain instanceof CookieCollectionInterface),
148 | 'getAll always need to return a collection of cookies, even if there is no domain'
149 | );
150 |
151 | $allDomain2 = $cookieCollection->getAll('domain2.dev');
152 |
153 | $this->assertTrue(
154 | ($allDomain2 instanceof CookieCollectionInterface)
155 | );
156 |
157 | $this->assertEquals($cookie3, $cookieCollection->get('cookie2'));
158 |
159 | $comparativeCollection = new CookieCollection([
160 | $cookie2,
161 | $cookie3
162 | ]);
163 |
164 | $this->assertEquals($allDomain2, $comparativeCollection);
165 | }
166 |
167 | public function testAddAndHas()
168 | {
169 | $cookie1 = (new Cookie())
170 | ->setDomain('domain1.dev')
171 | ->setName('cookie1')
172 | ->setValue('bar');
173 |
174 | $cookie2 = (new Cookie())
175 | ->setDomain('domain2.dev')
176 | ->setName('cookie2')
177 | ->setValue('baz');
178 |
179 | $cookie3 = (new Cookie())
180 | ->setDomain('domain1.dev')
181 | ->setName('only_for_domain1')
182 | ->setValue('biz');
183 |
184 | $cookie4 = (new Cookie())
185 | ->setName('should_be_added_on_both_domains')
186 | ->setValue('boz');
187 |
188 | $cookieCollection = new CookieCollection([
189 | $cookie1,
190 | $cookie2
191 | ]);
192 |
193 | /*cookie3 should only be added to domain1.dev*/
194 |
195 | $cookieCollection = $cookieCollection->add($cookie3);
196 |
197 | $this->assertTrue(
198 | ($cookieCollection instanceof CookieCollectionInterface),
199 | 'add function need to return CookieCollectionInterface'
200 | );
201 |
202 | $cookieCollection->add($cookie4);
203 |
204 | /*cookie4 should be added to both domain1.dev and domain2.dev*/
205 |
206 | $this->assertNotNull(
207 | $cookieCollection->get($cookie3->getName(), $cookie1->getDomain())
208 | );
209 |
210 | $this->assertNull(
211 | $cookieCollection->get($cookie3->getName(), $cookie2->getDomain())
212 | );
213 |
214 | $this->assertNotNull(
215 | $cookieCollection->get($cookie4->getName(), $cookie1->getDomain())
216 | );
217 |
218 | $this->assertNotNull(
219 | $cookieCollection->get($cookie4->getName(), $cookie2->getDomain())
220 | );
221 |
222 | /*test has*/
223 |
224 | $this->assertFalse($cookieCollection->has('do_not_exists'));
225 |
226 | $this->assertTrue($cookieCollection->has($cookie1->getName()));
227 |
228 | $this->assertTrue($cookieCollection->has($cookie1->getName(),
229 | $cookie1->getDomain()));
230 |
231 | $this->assertFalse($cookieCollection->has($cookie1->getName(),
232 | $cookie2->getDomain()));
233 |
234 | $this->assertTrue($cookieCollection->has($cookie4->getName(),
235 | $cookie1->getDomain()));
236 |
237 | $this->assertTrue($cookieCollection->has($cookie4->getName(),
238 | $cookie2->getDomain()));
239 | }
240 |
241 | public function testAddNoDomainEmptyCollection()
242 | {
243 | $this->expectException(CookieCollectionException::class);
244 |
245 | $collection = new CookieCollection();
246 | $collection->add(
247 | (new Cookie())
248 | ->setName('foo')
249 | ->setValue('bar')
250 | );
251 | }
252 |
253 | public function testDelete()
254 | {
255 | $cookie1 = (new Cookie())
256 | ->setDomain('domain1.dev')
257 | ->setName('cookie1')
258 | ->setValue('bar');
259 |
260 | $cookie2 = (new Cookie())
261 | ->setDomain('domain1.dev')
262 | ->setName('cookie2')
263 | ->setValue('bar');
264 |
265 | $cookie3 = (new Cookie())
266 | ->setDomain('domain2.dev')
267 | ->setName('cookie1')
268 | ->setValue('baz');
269 |
270 | $cookie4 = (new Cookie())
271 | ->setDomain('domain2.dev')
272 | ->setName('cookie2')
273 | ->setValue('baz');
274 |
275 | $cookieCollection = new CookieCollection([
276 | $cookie1,
277 | $cookie2,
278 | $cookie3,
279 | $cookie4,
280 | ]);
281 |
282 | /*remove cookie1 on both domains*/
283 |
284 | $cookieCollection = $cookieCollection->delete($cookie1->getName());
285 |
286 | $this->assertTrue(
287 | ($cookieCollection instanceof CookieCollectionInterface),
288 | 'remove function need to return CookieCollectionInterface'
289 | );
290 |
291 | $this->assertEquals(
292 | new CookieCollection([
293 | $cookie2,
294 | $cookie4,
295 | ]),
296 | $cookieCollection
297 | );
298 |
299 | /*we delete cookie2 only on domain1*/
300 |
301 | $cookieCollection->delete($cookie2->getName(), $cookie2->getDomain());
302 |
303 | $this->assertEquals(
304 | new CookieCollection([
305 | $cookie4,
306 | ]),
307 | $cookieCollection
308 | );
309 | }
310 |
311 | public function testDeleteAll()
312 | {
313 | $cookie1 = (new Cookie())
314 | ->setDomain('domain1.dev')
315 | ->setName('cookie1')
316 | ->setValue('bar');
317 |
318 | $cookie2 = (new Cookie())
319 | ->setDomain('domain1.dev')
320 | ->setName('cookie2')
321 | ->setValue('bar');
322 |
323 | $cookie3 = (new Cookie())
324 | ->setDomain('domain2.dev')
325 | ->setName('cookie1')
326 | ->setValue('baz');
327 |
328 | $cookie4 = (new Cookie())
329 | ->setDomain('domain2.dev')
330 | ->setName('cookie2')
331 | ->setValue('baz');
332 |
333 | $cookieCollection = new CookieCollection([
334 | $cookie1,
335 | $cookie2,
336 | $cookie3,
337 | $cookie4,
338 | ]);
339 |
340 | $cookieCollection = $cookieCollection->deleteAll();
341 |
342 | $this->assertTrue(
343 | ($cookieCollection instanceof CookieCollectionInterface),
344 | 'remove function need to return CookieCollectionInterface'
345 | );
346 |
347 | $this->assertEquals(new CookieCollection(),
348 | $cookieCollection->getAll());
349 |
350 | $cookieCollection = new CookieCollection([
351 | $cookie1,
352 | $cookie2,
353 | $cookie3,
354 | $cookie4,
355 | ]);
356 |
357 | $cookieCollection->deleteAll($cookie3->getDomain());
358 |
359 | $this->assertEquals(
360 | new CookieCollection([
361 | $cookie1,
362 | $cookie2,
363 | ]),
364 | $cookieCollection
365 | );
366 | }
367 |
368 | public function testToArrayAndJson()
369 | {
370 | $cookie1 = (new Cookie())
371 | ->setDomain('domain1.dev')
372 | ->setName('cookie1')
373 | ->setValue('bar');
374 |
375 | $cookie2 = (new Cookie())
376 | ->setDomain('domain1.dev')
377 | ->setName('cookie2')
378 | ->setValue('bar');
379 |
380 | $cookie3 = (new Cookie())
381 | ->setDomain('domain2.dev')
382 | ->setName('cookie1')
383 | ->setValue('baz');
384 |
385 | $cookieCollection = new CookieCollection([
386 | $cookie1,
387 | $cookie2,
388 | $cookie3,
389 | ]);
390 |
391 | $collectionToArray = $cookieCollection->toArray();
392 |
393 | $this->assertArrayHasKey($cookie1->getDomain(), $collectionToArray);
394 | $this->assertArrayHasKey($cookie3->getDomain(), $collectionToArray);
395 |
396 | $this->assertEquals(8,
397 | count($collectionToArray[$cookie1->getDomain()][$cookie1->getName()]));
398 | $this->assertEquals(8,
399 | count($collectionToArray[$cookie1->getDomain()][$cookie2->getName()]));
400 | $this->assertEquals(8,
401 | count($collectionToArray[$cookie3->getDomain()][$cookie3->getName()]));
402 |
403 | $this->assertEquals(
404 | json_encode($collectionToArray),
405 | json_encode($cookieCollection)
406 | );
407 | }
408 | }
409 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/Cookie/CookieTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(
18 | ($cookie instanceof CookieInterface),
19 | 'Cookie class need to implement CookieInterface'
20 | );
21 | }
22 |
23 | public function testCookieDomainParameter()
24 | {
25 | $domain = 'foo';
26 |
27 | $cookie = new Cookie();
28 | $this->assertEquals(null, $cookie->getDomain());
29 |
30 | $cookie->setDomain($domain);
31 | $this->assertEquals($domain, $cookie->getDomain());
32 | }
33 |
34 | public function testCookieHttpOnlyParameter()
35 | {
36 | $cookie = new Cookie();
37 | $this->assertFalse($cookie->isHttpOnly());
38 |
39 | $cookie->setHttpOnly(true);
40 | $this->assertTrue($cookie->isHttpOnly());
41 |
42 | $cookie = $cookie->setHttpOnly(false);
43 | $this->assertFalse($cookie->isHttpOnly());
44 | }
45 |
46 | public function testCookieFlagParameter()
47 | {
48 | $cookie = new Cookie();
49 | $this->assertTrue($cookie->isFlag());
50 |
51 | $cookie->setFlag(false);
52 | $this->assertFalse($cookie->isFlag());
53 |
54 | $cookie = $cookie->setFlag(true);
55 | $this->assertTrue($cookie->isFlag());
56 | }
57 |
58 | public function testCookiePathParameter()
59 | {
60 | $path = 'foo';
61 |
62 | $cookie = new Cookie();
63 | $this->assertEquals('/', $cookie->getPath());
64 |
65 | $cookie->setPath($path);
66 | $this->assertEquals($path, $cookie->getPath());
67 | }
68 |
69 | public function testCookieSecureParameter()
70 | {
71 | $cookie = new Cookie();
72 | $this->assertFalse($cookie->isSecure());
73 |
74 | $cookie->setSecure(true);
75 | $this->assertTrue($cookie->isSecure());
76 |
77 | $cookie->setSecure(false);
78 | $this->assertFalse($cookie->isSecure());
79 | }
80 |
81 | public function testCookieExpireParameter()
82 | {
83 | $expire = new DateTime();
84 |
85 | $cookie = new Cookie();
86 | $this->assertEquals(null, $cookie->getExpire());
87 |
88 | $cookie->setExpire($expire);
89 | $this->assertEquals($expire, $cookie->getExpire());
90 |
91 | $cookie->setExpire(null);
92 | $this->assertEquals(null, $cookie->getExpire());
93 | }
94 |
95 | public function testCookieNameParameter()
96 | {
97 | $name = 'foo';
98 |
99 | $cookie = new Cookie();
100 | $this->assertEquals('', $cookie->getName());
101 |
102 | $cookie->setName($name);
103 | $this->assertEquals($name, $cookie->getName());
104 | }
105 |
106 | public function testCookieValueParameter()
107 | {
108 | $value = 'foo';
109 |
110 | $cookie = new Cookie();
111 | $this->assertEquals('', $cookie->getValue());
112 |
113 | $cookie->setValue($value);
114 | $this->assertEquals($value, $cookie->getValue());
115 | }
116 |
117 | public function testToArrayAndJson()
118 | {
119 | $cookie = new Cookie();
120 |
121 | $cookieToArray = $cookie->toArray();
122 |
123 | $this->assertArrayHasKey('domain', $cookieToArray);
124 | $this->assertArrayHasKey('httpOnly', $cookieToArray);
125 | $this->assertArrayHasKey('flag', $cookieToArray);
126 | $this->assertArrayHasKey('path', $cookieToArray);
127 | $this->assertArrayHasKey('secure', $cookieToArray);
128 | $this->assertArrayHasKey('expire', $cookieToArray);
129 | $this->assertArrayHasKey('name', $cookieToArray);
130 | $this->assertArrayHasKey('value', $cookieToArray);
131 |
132 | $this->assertEquals(
133 | json_encode($cookieToArray),
134 | json_encode($cookie)
135 | );
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/CookieFileHandlerTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(
63 | $handler instanceof CookieFileHandlerInterface,
64 | 'CookieFileHandler class need to implement CookieFileHandlerInterface'
65 | );
66 | }
67 |
68 | public function testParseFile()
69 | {
70 | $handler = new CookieFileHandler(
71 | (new Configuration())->setCookieDir(self::COOKIE_PATH)
72 | );
73 |
74 | $cookieJar = $handler->parseFile(self::COOKIE_FILE_NAME);
75 |
76 | $this->assertTrue($cookieJar instanceof CookieJarInterface);
77 | }
78 |
79 | public function testParseFileWithoutConfiguration()
80 | {
81 | $this->expectException(NetscapeCookieFileHandlerException::class);
82 |
83 | $handler = new CookieFileHandler();
84 | $handler->parseFile(self::COOKIE_FILE_NAME);
85 | }
86 |
87 | public function testParseContent()
88 | {
89 | $handler = new CookieFileHandler();
90 | $cookieJar = $handler->parseContent('');
91 |
92 | $this->assertTrue($cookieJar instanceof CookieCollectionInterface);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/Jar/CookieJarPersisterTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(
39 | $persister instanceof PersisterInterface,
40 | 'CookieJarPersister class need to implement CookieJarPersisterInterface'
41 | );
42 | }
43 |
44 | public function testPersistWithoutCookieDirParameter()
45 | {
46 | $this->expectException(PersisterException::class);
47 |
48 | $persister
49 | = new Persister((new Configuration())->setCookieDir(''));
50 | $persister->persist(
51 | new CookieCollection(),
52 | CookieFileHandlerTest::COOKIE_TEST_FILE_NAME
53 | );
54 | }
55 |
56 | public function testImcompleteCookie()
57 | {
58 | $persister = new Persister(
59 | (new Configuration())
60 | ->setCookieDir(CookieFileHandlerTest::COOKIE_PATH)
61 | );
62 |
63 | /*clean test file*/
64 |
65 | $persister->persist(
66 | new CookieCollection(),
67 | CookieFileHandlerTest::COOKIE_TEST_FILE_NAME
68 | );
69 |
70 | /*cookie default path should be converted to "/" */
71 |
72 | $persister->persist(
73 | new CookieCollection([
74 | (new Cookie)
75 | ->setDomain('foo.bar')
76 | ->setPath('')
77 | ->setName('foo')
78 | ->setValue('bar'),
79 | ]),
80 | CookieFileHandlerTest::COOKIE_TEST_FILE_NAME
81 | );
82 |
83 | $this->assertEquals(
84 | '/',
85 | $this->getCookieJar()->get('foo')->getPath()
86 | );
87 | }
88 |
89 | /**
90 | * @return CookieJarInterface
91 | */
92 | private function getCookieJar() : CookieJarInterface
93 | {
94 | $handler = new CookieFileHandler(
95 | (new Configuration())->setCookieDir(CookieFileHandlerTest::COOKIE_PATH)
96 | );
97 |
98 | return $handler->parseFile(CookieFileHandlerTest::COOKIE_TEST_FILE_NAME);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/Jar/CookieJarTest.php:
--------------------------------------------------------------------------------
1 | setCookieDir(CookieFileHandlerTest::COOKIE_PATH),
38 | CookieFileHandlerTest::COOKIE_TEST_FILE_NAME
39 | );
40 |
41 | $this->assertTrue(
42 | $jar instanceof CookieJarInterface,
43 | 'CookieJar class need to implement CookieJarInterface'
44 | );
45 | }
46 |
47 | public function testGetterSetterCookiesFile()
48 | {
49 | $file = 'foo.txt';
50 |
51 | $cookieJar = $this->getCookieJar();
52 | $cookieJar->setCookiesFile($file);
53 |
54 | $this->assertEquals($file, $cookieJar->getCookiesFile());
55 | }
56 |
57 | public function testGetterSetterCookies()
58 | {
59 | $cookieJar = $this->getCookieJar();
60 |
61 | $cookies = $cookieJar->getCookies();
62 | $this->assertTrue($cookies instanceof CookieCollectionInterface);
63 |
64 | $cookieJar->setCookies(new CookieCollection());
65 | $cookies = $cookieJar->getCookies();
66 | $this->assertEquals(0, count($cookies->toArray()));
67 | }
68 |
69 | public function testGetAndGetAll()
70 | {
71 | $cookieJar = $this->getCookieJar();
72 | $this->assertTrue($cookieJar->get('key_a') instanceof CookieInterface);
73 | $this->assertTrue($cookieJar->getAll() instanceof
74 | CookieCollectionInterface);
75 | }
76 |
77 | public function testAddAndDelete()
78 | {
79 | $cookieDomain = 'domain1.dev';
80 | $cookieName = 'foo';
81 | $cookieValue = 'bar';
82 |
83 | $cookieJar = $this->getCookieJar();
84 |
85 | $cookieJar->add(
86 | (new Cookie())
87 | ->setDomain($cookieDomain)
88 | ->setName($cookieName)
89 | ->setValue($cookieValue)
90 | )->persist();
91 |
92 | /*read the cookie file again and check if new cookie is here*/
93 |
94 | $cookieJar = $this->getCookieJar();
95 | $this->assertTrue($cookieJar->has($cookieName, $cookieDomain));
96 |
97 | /*compare files with expected result*/
98 |
99 | $this->assertFileEquals(
100 | CookieFileHandlerTest::EXPECTED_COOKIE_FILE,
101 | CookieFileHandlerTest::COOKIE_TEST_FILE
102 | );
103 |
104 | /*test delete*/
105 |
106 | $cookieJar->delete($cookieName)->persist();
107 |
108 | /*read the cookie file again and check if new cookie is here*/
109 |
110 | $cookieJar = $this->getCookieJar();
111 | $this->assertFalse($cookieJar->has($cookieName, $cookieDomain));
112 | }
113 |
114 | public function testDeleteAll()
115 | {
116 | $cookieJar = $this->getCookieJar();
117 | $cookieJar->deleteAll()->persist();
118 | $this->assertFalse(file_exists(CookieFileHandlerTest::COOKIE_TEST_FILE));
119 | }
120 |
121 | /**
122 | * @return CookieJarInterface
123 | */
124 | private function getCookieJar() : CookieJarInterface
125 | {
126 | $handler = new CookieFileHandler(
127 | (new Configuration())->setCookieDir(CookieFileHandlerTest::COOKIE_PATH)
128 | );
129 |
130 | return $handler->parseFile(CookieFileHandlerTest::COOKIE_TEST_FILE_NAME);
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/Parser/ParserTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(
21 | $parser instanceof ParserInterface,
22 | 'Parser class need to implement ParserInterface'
23 | );
24 | }
25 |
26 | public function testParseFile()
27 | {
28 | $expectedCookiesArray = [
29 | 'domain1.dev' => [
30 | 'key_a' => [
31 | 'domain' => 'domain1.dev',
32 | 'httpOnly' => false,
33 | 'flag' => false,
34 | 'path' => '/',
35 | 'secure' => false,
36 | 'expire' => null,
37 | 'name' => 'key_a',
38 | 'value' => 'value a',
39 | ],
40 | 'key_b' => [
41 | 'domain' => 'domain1.dev',
42 | 'httpOnly' => true,
43 | 'flag' => true,
44 | 'path' => '/',
45 | 'secure' => true,
46 | 'expire' => new \DateTime(date('Y-m-d H:i:s', 1486849760)),
47 | 'name' => 'key_b',
48 | 'value' => '123',
49 | ],
50 | ],
51 | 'domain2.dev' => [
52 | 'key_a' => [
53 | 'domain' => 'domain2.dev',
54 | 'httpOnly' => false,
55 | 'flag' => false,
56 | 'path' => '/foo',
57 | 'secure' => true,
58 | 'expire' => null,
59 | 'name' => 'key_a',
60 | 'value' => 'true',
61 | ],
62 | ]
63 | ];
64 |
65 | $parser = new Parser(
66 | (new Configuration())->setCookieDir(CookieFileHandlerTest::COOKIE_PATH)
67 | );
68 |
69 | $cookies = $parser->parseFile(CookieFileHandlerTest::COOKIE_FILE_NAME);
70 |
71 | $this->assertTrue($cookies instanceof CookieCollectionInterface);
72 |
73 | $this->assertEquals(
74 | $expectedCookiesArray,
75 | $cookies->getAll()->toArray()
76 | );
77 |
78 | $this->assertEquals(
79 | $cookies,
80 | $parser->parseContent(file_get_contents(CookieFileHandlerTest::COOKIE_FILE))
81 | );
82 | }
83 |
84 | public function testParseFileMissingConfig()
85 | {
86 | $this->expectException(ParserException::class);
87 |
88 | $parser = new Parser();
89 | $parser->parseFile(CookieFileHandlerTest::COOKIE_FILE_NAME);
90 | }
91 |
92 | public function testParseFileMissingDirConfig()
93 | {
94 | $this->expectException(ParserException::class);
95 |
96 | $parser = new Parser((new Configuration())->setCookieDir(''));
97 | $parser->parseFile(CookieFileHandlerTest::COOKIE_FILE_NAME);
98 | }
99 |
100 | public function testParseUnknownFile()
101 | {
102 | $this->expectException(ParserException::class);
103 |
104 | $parser
105 | = new Parser((new Configuration())->setCookieDir(CookieFileHandlerTest::COOKIE_PATH));
106 | $parser->parseFile('unknown_file');
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/_files/cookies/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 | !example.txt
4 | !example_expected.txt
5 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/_files/cookies/example.txt:
--------------------------------------------------------------------------------
1 | # Netscape HTTP Cookie File
2 | # http://curl.haxx.se/docs/http-cookies.html
3 | # This file was generated by libcurl! Edit at your own risk.
4 |
5 | #disabled.dev TRUE / TRUE 0 a b
6 | domain1.dev FALSE / FALSE 0 key_a value a
7 | #HttpOnly_domain1.dev TRUE / TRUE 1486849760 key_b 123
8 | domain2.dev FALSE /foo TRUE 0 key_a true
9 |
--------------------------------------------------------------------------------
/tests/NetscapeCookieFileHandler/_files/cookies/example_expected.txt:
--------------------------------------------------------------------------------
1 | # Netscape HTTP Cookie File
2 | # This file was generated by "netscape-cookie-file-handler" free PHP7 tool
3 | # https://github.com/kegi/netscape-cookie-file-handler
4 |
5 | domain1.dev FALSE / FALSE 0 key_a value a
6 | #HttpOnly_domain1.dev TRUE / TRUE 1486849760 key_b 123
7 | domain1.dev TRUE / FALSE 0 foo bar
8 | domain2.dev FALSE /foo TRUE 0 key_a true
9 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |