[
  {
    "path": ".gitignore",
    "content": "/node_modules\n.DS_Store\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img width=\"150\" src=\"logo.png\" alt=\"胖鼠采集\">\n  <br>\n  <br>\n</p>\n\n### <a href=\"https://www.fatrat.cn\">胖鼠采集</a> WordPress优秀开源采集插件\n- 微信公众号文章采集 - 强大的Jquery可以处理各种版权信息, 纵享丝滑.\n- 微信公众号历史文章采集 - 采集公众号所有的历史文章.\n- 登陆网站采集 - 采集网站登录后的内容.\n- 简书文章采集 - 强大的Jquery可以处理内容各种图片, 柔顺到底.\n- 知乎问答采集 - 强大的Jquery可以处理各种你不想要的东西, 一键爽歪歪.\n- (独家主打) 列表采集，历史采集 <a href=\"https://www.fatrat.cn/docs/v2/list-paging-collection\" target=\"_blank\">视频文字教程</a>- 只需轻轻一点. 数不清的文章就来了.\n- (独家主打) 详情页面文章采集 - 任何网站十秒搞定\n- (独家主打) <a href=\"https://www.fatrat.cn/docs/v2/list-paging-collection\" target=\"_blank\">分页爬取</a> - 历史数据, 也不放过. 一网打尽\n- (胖鼠主打) 自动采集 - 一键启动不放过每一份数据.\n- (胖鼠主打) 自动发布 - 您省心省力好帮手.\n- (独家主打) 调试模式 - 新建规则好帮手, 采集结果好伙伴.\n- (独家主打) 体验例子 - 一键体验胖鼠.\n- (主打主打) 文章自动添加, <a href=\"https://www.fatrat.cn/docs/v2/dynamic-content\" target=\"_blank\">动态内容</a>, <a href=\"https://www.fatrat.cn/docs/v2/auto-tags\" target=\"_blank\">自动标签</a>, 标签内链, 优化SEO.\n- (胖鼠采集) 文章滤重 - 支持.\n- (胖鼠采集) 自动特色图片 - 支持.\n- (胖鼠采集) 采集图片加入媒体库 - 支持.\n- (胖鼠采集) 数据处理 - 完美支持Html Jquery\n- (胖鼠采集) 内容关键字过滤替换 伪原创 - 支持.\n- (胖鼠采集) 自定义采集任何可见网站 - 完美支持.\n- (胖鼠采集) 自定义文章图片链接类型 - 支持.\n- (重磅重磅) 胖鼠采集完全基于Wordpress, 安装即用, 开源作品\n- (声明声明) 如你的PHP版本小于PHP71, 请移步胖鼠采集的Github下载使用胖鼠v5版本 分支名: based_php_5.6\n- (声明声明) 胖鼠采集初衷为参考学习交流; 请大家遵纪守法. 抵制违法犯罪, 作者不承担任何法律风险.\n- (声明声明) 胖鼠采集开源可供您查阅代码, 或者二次开发使用供您使用, 但不可修改源码后用于商业行为.\n- ...\n\n## 安装\n- 在插件中搜索 <strong><a href=\"https://wordpress.org/plugins/fat-rat-collect/\">胖鼠采集</a></strong> 安装即可\n- 将插件文件上传到/wp-content/plugins/目录 即可\n- PHP版本小于PHP71, 请移步胖鼠采集的Github下载使用胖鼠v5版本 分支名: based_php_5.6\n- 推荐环境\n- PHP7.2 或 PHP7.3\n- MYSQL5.7 或 MYSQL5.6\n\n## 系统分为五大块.\n- 胖鼠强大的爬虫中心\n- 支撑胖鼠的配置中心\n- 发布文章的数据桶\n- 调试中心debugging\n- 工具箱特色小工具\n\n## 作者留言\n- 安装后可一键导入演示例子, 大家可以照葫芦画瓢.\n- 胖鼠采集 1群: 454049736(已满)\n- 胖鼠采集 2群: 846069514(已满)\n- 胖鼠采集 3群: (已满)\n- 胖鼠采集 4群: waxx-xxswnb 添加胖鼠微信\n- 疑问：为什么会上传vendor目录，答：wordpress插件是不能composer install\n\n## Star History\n\n<a href=\"https://www.star-history.com/?repos=KitePig%2FFatRat-Collect&type=date&legend=top-left\">\n <picture>\n   <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/chart?repos=KitePig/FatRat-Collect&type=date&theme=dark&legend=top-left\" />\n   <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/chart?repos=KitePig/FatRat-Collect&type=date&legend=top-left\" />\n   <img alt=\"Star History Chart\" src=\"https://api.star-history.com/chart?repos=KitePig/FatRat-Collect&type=date&legend=top-left\" />\n </picture>\n</a>\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"require\": {\n        \"jaeger/querylist\": \"^4.2\",\n        \"jaeger/querylist-puppeteer\": \"^4.0\",\n        \"tightenco/collect\": \"8.78.0\",\n        \"ext-json\": \"*\"\n    },\n    \"require-dev\": {\n        \"symfony/var-dumper\": \"^5.0\"\n    },\n    \"autoload\": {\n        \"files\": [\n            \"src/Helpers/helpers.php\",\n            \"src/Helpers/helpers2.php\",\n            \"src/Controller/TaskController.php\",\n            \"includes/fatrat-apierror.php\",\n            \"includes/fatrat-spider.php\",\n            \"includes/fatrat-options.php\",\n            \"includes/fatrat-options-add-edit.php\",\n            \"includes/fatrat-data.php\",\n            \"includes/fatrat-data-detail.php\",\n            \"includes/fatrat-validation.php\",\n            \"includes/fatrat-kit.php\",\n            \"includes/fatrat-debugging.php\"\n        ]\n    }\n}\n"
  },
  {
    "path": "fatratcollect.php",
    "content": "<?php\n/**\n * Plugin Name: Fat Rat Collect\n * Plugin URI: https://www.fatrat.cn\n * Description: 胖鼠采集(Fat Rat Collect) 是一款可以帮助你批量采集文章数据的开源插件，采集含括微信采集、公众号历史采集、登陆网站采集、简书采集、知乎采集、列表采集、详情采集。完美支持自动采集、自动发布文章。图片本地化、关键字替换、自动标签、动态内容、等其他黑科技。是您建站好帮手！如果你还会一点Html JQuery知识。那就太棒了。\n * Version: 2.7.5\n * Author: Fat Rat\n * Author URI: https://www.fatrat.cn/about\n * Disclaimer: Use at your own risk. No warranty expressed or implied is provided.\n * Text Domain: fat-rat-collect\n * License: GPL3\n */\n\n// If this file is called directly, abort.\nif (!defined('WPINC')) {\n    die;\n}\n\nglobal $frc_db_version;\n$frc_db_version = '2.7.1';\n\n/**\n * Fire up Composer's autoloader\n */\nrequire (__DIR__ . '/vendor/autoload.php');\n\n/**\n * Install\n */\nfunction frc_plugin_install(){\n    global $wpdb;\n    global $frc_db_version;\n\n    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );\n\n    $table_post      = $wpdb->prefix . 'frc_post';\n    $table_options   = $wpdb->prefix . 'frc_options';\n    $charset_collate = $wpdb->get_charset_collate();\n\n    $sql =\n        \"CREATE TABLE IF NOT EXISTS $table_options(\n          `id` int(11) NOT NULL AUTO_INCREMENT,\n          `collect_name` varchar(30) NOT NULL DEFAULT '',\n          `collect_describe` varchar(200) NOT NULL DEFAULT '',\n          `collect_type` varchar(20) NOT NULL DEFAULT '',\n          `collect_list_url` varchar(191) NOT NULL DEFAULT '',\n          `collect_list_url_paging` varchar(191) NOT NULL DEFAULT '',\n          `collect_list_range` varchar(191) NOT NULL DEFAULT '',\n          `collect_list_rules` varchar(1000) NOT NULL DEFAULT '',\n          `collect_content_range` varchar(191) NOT NULL DEFAULT '',\n          `collect_content_rules` varchar(1000) NOT NULL DEFAULT '',\n          `collect_charset` varchar(20) NOT NULL DEFAULT 'utf-8',\n          `collect_cookie` varchar(5000) NOT NULL DEFAULT '',\n          `collect_image_download` tinyint(10) NOT NULL DEFAULT '1',\n          `collect_image_path` tinyint(2) NOT NULL DEFAULT '1',\n          `collect_image_attribute` varchar(20) NOT NULL DEFAULT 'src',\n          `collect_rendering` tinyint(2) NOT NULL DEFAULT '1',\n          `collect_remove_head` tinyint(2) NOT NULL DEFAULT '1',\n          `collect_auto_collect` tinyint(2) NOT NULL DEFAULT '2',\n          `collect_auto_release` tinyint(2) NOT NULL DEFAULT '2',\n          `collect_release` varchar(191) NOT NULL DEFAULT '{}',\n          `collect_keywords_replace_rule` mediumtext NOT NULL,\n          `collect_custom_content` mediumtext NOT NULL,\n          `collect_keywords` text NOT NULL DEFAULT '',\n          `created_at` timestamp NULL DEFAULT NULL,\n          `updated_at` timestamp NULL DEFAULT NULL,\n          PRIMARY KEY (`id`)\n        )\t$charset_collate; \";\n    dbDelta( $sql );\n\n    $sql =\n        \"CREATE TABLE IF NOT EXISTS $table_post(\n            `id` int(11) NOT NULL AUTO_INCREMENT,\n            `option_id` int(11) NOT NULL,\n            `status` tinyint(5) NOT NULL DEFAULT '1',\n            `title` varchar(120) NOT NULL DEFAULT '',\n            `cover` varchar(191) NOT NULL DEFAULT '',\n            `content` mediumtext NOT NULL,\n            `link` varchar(191) NOT NULL DEFAULT '',\n            `post_id` int(11) NOT NULL DEFAULT '0',\n            `message` varchar(191) NOT NULL DEFAULT '',\n            `created_at` timestamp NULL DEFAULT NULL,\n            `updated_at` timestamp NULL DEFAULT NULL,\n            PRIMARY KEY (`id`),\n            KEY `option_id` (`option_id`),\n            KEY `status` (`status`),\n            UNIQUE KEY `link` (`link`)\n        )\t$charset_collate; \";\n    dbDelta( $sql );\n\n    add_option( 'frc_db_version', $frc_db_version );\n    add_option( 'frc_install_time', time() );\n}\nregister_activation_hook( __FILE__, 'frc_plugin_install' );\n\n/**\n * Update\n */\nfunction frc_plugin_update() {\n    global $frc_db_version;\n\n    if ( get_option( 'frc_db_version' ) != $frc_db_version ) {\n        global $wpdb;\n        $wpdb->show_errors();\n\n        frcAddColumn('collect_keywords', 'text NOT NULL DEFAULT \"\" AFTER `collect_custom_content`', 'option');\n        frcChangeColumn('MODIFY COLUMN `collect_list_rules` varchar(1000) not null default \"\"','option');\n        frcChangeColumn('MODIFY COLUMN `collect_content_rules` varchar(1000) not null default \"\"','option');\n        frcAddColumn('collect_cookie', 'varchar(5000) NOT NULL DEFAULT \"\" AFTER `collect_charset`', 'option');\n        if (!get_option('frc_mysql_upgrade')){\n            $former_table_options = $wpdb->prefix . 'fr_options';\n            $res = $wpdb->get_results(\"SHOW TABLES LIKE '%{$former_table_options}%'\");\n            if (!empty($res)){\n                update_option('frc_mysql_upgrade', '1');\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => '配置表升级完成.'];\n            } else {\n                $former_table_post = $wpdb->prefix . 'fr_post';\n                $res = $wpdb->get_results(\"SHOW TABLES LIKE '%{$former_table_post}%'\");\n                if (!empty($res)){\n                    add_option('frc_mysql_upgrade', '2');\n                } else {\n                    add_option('frc_mysql_upgrade', 'upgrade complete');\n                }\n            }\n\n            $config = json_encode(['switch' => 'shutdown', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql')]);\n            if (get_option(FRC_Validation::FRC_VALIDATION_FEATURED_PICTURE)){\n                update_option(FRC_Validation::FRC_VALIDATION_FEATURED_PICTURE, $config);\n            }\n            if (get_option(FRC_Validation::FRC_VALIDATION_DYNAMIC_FIELDS)){\n                update_option(FRC_Validation::FRC_VALIDATION_DYNAMIC_FIELDS, $config);\n            }\n            if (get_option(FRC_Validation::FRC_VALIDATION_AUTO_TAGS)){\n                update_option(FRC_Validation::FRC_VALIDATION_AUTO_TAGS, $config);\n            }\n        }\n\n        frc_plugin_install();\n    }\n\n    update_option('frc_db_version', $frc_db_version);\n}\nadd_action( 'plugins_loaded', 'frc_plugin_update' );\n\n/**\n * Style && Script\n */\nfunction frc_loading_assets( $hook ) {\n    global $frc_db_version;\n    $allowed_pages = array(\n        'frc-collect',\n        'frc-spider',\n        'frc-options',\n        'frc-data',\n        'frc-options-add-edit',\n        'frc-kit',\n        'frc-data-detail',\n        'frc-debugging'\n    );\n\n    if (in_array(strstr($hook,\"frc-\"), $allowed_pages)) {\n        // css\n        wp_register_style('fat-rat-bootstrap-css', plugins_url('public/css/bootstrap.min.css', __FILE__));\n        wp_enqueue_style('fat-rat-bootstrap-css');\n        wp_register_style('fat-rat-css', plugins_url('public/css/fatrat.css', __FILE__));\n        wp_enqueue_style('fat-rat-css');\n\n        // js\n        wp_register_script('fat-rat-bootstrap-js', plugins_url('public/js/bootstrap.min.js', __FILE__));\n        wp_enqueue_script('fat-rat-bootstrap-js');\n        wp_register_script('fat-rat-js', plugins_url('public/js/fatrat.js', __FILE__), array('jquery'), $frc_db_version, true);\n        wp_enqueue_script('fat-rat-js');\n    }\n}\nadd_action( 'admin_enqueue_scripts', 'frc_loading_assets' );\n\n/**\n * Menu\n */\nfunction frc_loading_menu()\n{\n    add_menu_page(\n        __('胖鼠采集', 'Fat Rat Collect'),\n        __('胖鼠采集', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-collect',\n        'frc_spider',\n        plugins_url('images/', __FILE__) . 'fat-rat.png'\n    );\n\n    add_submenu_page(\n        'frc-collect',\n        __('采集中心', 'Fat Rat Collect'),\n        __('采集中心', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-spider',\n        'frc_spider'\n    );\n\n    add_submenu_page(\n        'frc-collect',\n        __('配置中心', 'Fat Rat Collect'),\n        __('配置中心', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-options',\n        'frc_options'\n    );\n\n    add_submenu_page(\n        'frc-collect',\n        __('数据桶中心', 'Fat Rat Collect'),\n        __('数据桶中心', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-data',\n        'frc_data_list'\n    );\n\n    add_submenu_page(\n        'frc-collect',\n        __('添加/修改(配置)', 'Fat Rat Collect'),\n        __('添加/修改(配置)', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-options-add-edit',\n        'frc_options_add_edit'\n    );\n\n    add_submenu_page(\n        'frc-collect',\n        __('Debugging', 'Fat Rat Collect'),\n        __('Debugging', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-debugging',\n        'frc_debugging'\n    );\n\n    add_submenu_page(\n        '',\n        __('数据列表', 'Fat Rat Collect'),\n        __('数据列表', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-data-detail',\n        'frc_data_detail'\n    );\n\n    add_submenu_page(\n        'frc-collect',\n        __('胖鼠工具箱', 'Fat Rat Collect'),\n        __('胖鼠工具箱', 'Fat Rat Collect'),\n        'manage_options',\n        'frc-kit',\n        'frc_kit'\n    );\n\n//    add_submenu_page(\n//        'frc-collect',\n//        __('任务中心', 'Fat Rat Collect'),\n//        __('任务中心', 'Fat Rat Collect'),\n//        'manage_options',\n//        'frc-tasks',\n//        function (){\n//            (new TaskController())->view();\n//        }\n//    );\n\n    remove_submenu_page('frc-collect', 'frc-collect');\n//    remove_submenu_page('frc-collect', 'frc-data-detail');\n}\nadd_action('admin_menu', 'frc_loading_menu');\n\nif (!function_exists('frc_write_log')){\n    function frc_write_log($string, $file_name = '')\n    {\n        if (is_array($string)){\n            $string = json_encode($string);\n        }\n        $time = current_time('timestamp');\n        $file_name = 'frc.log'.'-'.date('Ymd').($file_name!=''?'-'.$file_name:'');\n        $content = sprintf('[%s] %s '.\"\\n\", date('Y-m-d H:i:s', $time), $string);\n        file_put_contents(plugin_dir_path( __FILE__ ).'logs/'.$file_name, $content,FILE_APPEND);\n    }\n}\n/**\n * Require ..\n * 开发者您好，您可修改源码自行使用\n * 但请不要修改胖鼠采集代码后用于其他组织/商业行为\n */\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-apierror.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-spider.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-options.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-options-add-edit.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-data.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-data-detail.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-validation.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-kit.php' );\n//require_once( plugin_dir_path( __FILE__ ) . 'includes/fatrat-debugging.php' );\n\nadd_action( 'wp_ajax_frc_interface', function (){\n    $s_time = microtime(true);\n    if(version_compare(PHP_VERSION,'7.1.0', '<')){\n        wp_send_json(['code' => 5003, 'msg' => '鼠友你好, 胖鼠采集目前要求php版本 > 7.1, 检测到你当前PHP版本为'.phpversion().'. 建议升级php版本, 或者请去胖鼠采集的Github下载使用胖鼠v5.6版本 分支名: based_php_5.6!']);\n        wp_die();\n    }\n    $interface_type = frc_sanitize_text('interface_type', null);\n    if (empty($interface_type)){\n        wp_send_json(['code' => 5004, 'msg' => 'interface type not found error!']);\n        wp_die();\n    }\n\n    $action_func = frc_sanitize_text('action_func');\n    if (empty($action_func)){\n        wp_send_json(['code' => 5001, 'msg' => 'Parameter error!']);\n        wp_die();\n    }\n\n    if(get_option('fat_rat_collect_api_code') === \"4\".\"03\"){\n        (new FRC_Validation())->validation_correction();\n        (new FRC_Validation())->report_permissions();\n        sleep(5);\n        wp_send_json(['code' => 5005, 'msg' => FRC_Validation::FRC_HINT_K]);\n        wp_die();\n    }\n\n    $action_csrf = frc_sanitize_text('csrf');\n\tif (empty($action_csrf)){\n\t\twp_send_json(['code' => 5007, 'msg' => '安全校验失败！请强制刷新页面缓存，如异常持续请联系作者。']);\n\t\twp_die();\n\t}\n    if(!current_user_can( 'manage_options' ) || !wp_verify_nonce($action_csrf)){\n        wp_send_json(['code' => 5006, 'msg' => FRC_Validation::FRC_HINT_M]);\n        wp_die();\n    }\n\n    $result = null;\n    if ($interface_type == '1'){\n        $action_func = 'grab_'.$action_func;\n        $model = new FRC_Spider();\n    } elseif($interface_type == '2'){\n        $action_func = 'interface_'.$action_func;\n        $model = new FRC_Options();\n    } elseif($interface_type == '3'){\n        $action_func = 'data_'.$action_func;\n        $model = new FRC_Data();\n    } elseif($interface_type == '4'){\n        $action_func = 'validation_'.$action_func;\n        $model = new FRC_Validation();\n    } else {\n        $model = null;\n    }\n\n    method_exists($model, $action_func) && $result = $model->$action_func();\n    if ($result != null){\n        $result['cost'] = round(microtime(true ) - $s_time, 2).'秒';\n        wp_send_json($result);\n        wp_die();\n    }\n    wp_send_json(['code' => 5002, 'result' => $result, 'msg' => 'Action there is no func! or Func is error!']);\n    wp_die();\n});\n\n/**\n * add cron operating time\n * @return array\n */\nfunction frc_more_schedules() {\n    return array(\n        'fifteenminutes' => array('interval' => 900, 'display' => '每隔十五分钟'),\n        'halfhour' => array('interval' => 1800, 'display' => '每隔半小时'),\n        'twohourly' => array('interval' => 7200, 'display' => '每隔两小时'),\n        'threehours' => array('interval' => 10800, 'display' => '每隔三小时'),\n        'fourhourly' => array('interval' => 14400, 'display' => '每隔四小时'),\n        'eighthourly' => array('interval' => 28800, 'display' => '每隔八小时'),\n    );\n}\nadd_filter('cron_schedules', 'frc_more_schedules');\n\nfunction frc_spider_timing_task()\n{\n    return (new FRC_Spider())->timing_spider();\n}\n\nif ($frc_cron_spider = get_option('frc_cron_spider')){\n    if (!wp_next_scheduled('frc_cron_spider_hook')) {\n        wp_schedule_event(time(), $frc_cron_spider, 'frc_cron_spider_hook');\n    }\n    add_action('frc_cron_spider_hook', 'frc_spider_timing_task');\n} else {\n    wp_clear_scheduled_hook('frc_cron_spider_hook');\n}\n\nif ($frc_cron_release = get_option('frc_cron_release')){\n    if (!wp_next_scheduled('frc_cron_release_hook')) {\n        wp_schedule_event(time(), $frc_cron_release, 'frc_cron_release_hook');\n    }\n\n    add_action('frc_cron_release_hook', 'frc_cron_release_task');\n    function frc_cron_release_task()\n    {\n        return (new FRC_Data())->data_automatic_release();\n    }\n} else {\n    wp_clear_scheduled_hook('frc_cron_release_hook');\n}\n\n/**\n * Uninstall\n */\nfunction frc_plugin_uninstall() {\n    global $wpdb;\n    $table_o_post     = $wpdb->prefix . 'fr_post';\n    $table_o_options  = $wpdb->prefix . 'fr_options';\n    $wpdb->query( \"DROP TABLE IF EXISTS $table_o_options\" );\n    $wpdb->query( \"DROP TABLE IF EXISTS $table_o_post\" );\n\n    delete_option( 'frc_db_version' );\n    delete_option( 'frc_mysql_upgrade_progress' );\n\n    foreach (FRC_Validation::FRC_VALIDATION_ABILITY_MAP as $value){\n        delete_option( $value[0] );\n    }\n\n    $table_post     = $wpdb->prefix . 'frc_post';\n    $table_options  = $wpdb->prefix . 'frc_options';\n\n    $wpdb->query( \"DROP TABLE IF EXISTS $table_options\" );\n    $wpdb->query( \"DROP TABLE IF EXISTS $table_post\" );\n\n}\nregister_uninstall_hook(__FILE__, 'frc_plugin_uninstall');"
  },
  {
    "path": "includes/fatrat-apierror.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2018年12月30日 02:24\n */\n\n/**\n * Class FRC_ApiError\n * 有空再整把\n */\nclass FRC_ApiError\n{\n    // TODO 只用了 SUCCESS FAIL\n\n    /**\n     * 业务常量\n     */\n    const BUTTON_DISABLED     = ['微信', '简书', '知乎'];\n    const FRC_TIPS     = [\n        '小提示: 写采集规则的时候, 如果页面最后一个div是广告,你可以这么写 -div:last 即可删除内容中最后一个 div 删除第一个 -div:first 同样适用于其他标签哦 =_=!',\n        '小提示: 列表采集 是通过列表页拿到一批详情的地址, 然后批量采集详情页面数据。详情采集是直接采集文章详情页面喔 =_=!',\n        '小提示: 大家可在胖鼠Q群联系作者, 提出更好的胖鼠改进计划, 好思路有奖喔 =_=!',\n        '小提示: 规则配置页采集区域? 是指你具体要采集这个页面的哪一块内容, 你要采集的内容必须包含在采集区域内哦 =_=!',\n        '小提示: 规则详情配置为什么没有采集地址这一栏? 答:因为详情配置是单篇文章配置, 把采集地址拎出来更有效帮助你批量采集哦 =_=!',\n        '小提示: 使用DEBUG的时候, 大家一定要把 Link Title Content 三个字段全部debug成功之后再保存哦, 有助于提高成功率 =_=!',\n    ];\n\n    /**\n     * 基本错误类型\n     */\n    const SUCCESS       = 200;\n    const FAIL          = 0;\n    const ERR_PARAM     = -100;\n    const ERR_TOKEN     = -180;\n\n    /**\n     * Validation\n     * @var array\n     */\n    const CHECK_SERVER_FAIL = -4000;\n    const KEYWORD_CHECK_FAIL = -4001;\n    const NO_PERMISSION = -4002;\n\n\n    private static $_errMsg = [\n        // 基础错误\n        self::SUCCESS       => ['成功', 'success'],\n        self::FAIL          => ['失败', 'fail'],\n        self::ERR_PARAM     => ['参数错误', 'parameter is error'],\n        self::ERR_TOKEN     => ['Token错误', 'token error'],\n\n        // Validation\n        self::CHECK_SERVER_FAIL => ['验证服务器异常', 'check server is error'],\n        self::KEYWORD_CHECK_FAIL => ['口令错误', 'keyword is error'],\n        self::NO_PERMISSION => ['没有许可', 'you no permission'],\n    ];\n\n\n    public static function msg($errno, $lang = 'en')\n    {\n        $lang = 'zh' === $lang ? 0 : 1;\n        return self::$_errMsg[$errno][$lang];\n    }\n\n}\n"
  },
  {
    "path": "includes/fatrat-data-detail.php",
    "content": "<?php\n\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2018年12月30日 02:24\n */\n\nclass FRC_Data\n{\n    protected $wpdb;\n    protected $table_post;\n\n    public function __construct()\n    {\n        global $wpdb;\n        $this->wpdb = $wpdb;\n        $this->table_post = $wpdb->prefix . 'frc_post';\n\n    }\n\n    public function id($id){\n        return $this->wpdb->get_row(\n            $this->wpdb->prepare(\"select * from $this->table_post where `id` =  %d\", $id),\n            ARRAY_A\n        );\n    }\n\n    public function getDataByOption($option_id, $count = 1, $sort = 'ASC'){\n\t    $sort = strtoupper($sort) == 'ASC' ? 'ASC' : 'DESC';\n        return $this->wpdb->get_results(\n            $this->wpdb->prepare(\"select * from $this->table_post where `option_id` = %d AND `status` = 2  ORDER BY `id` $sort LIMIT %d\", $option_id, $count),\n            ARRAY_A\n        );\n    }\n\n    public function getWaitDataByOption($option_id, $count = 1, $sort = 'ASC'){\n        $sort = strtoupper($sort) == 'ASC' ? 'ASC' : 'DESC';\n        return $this->wpdb->get_results(\n            $this->wpdb->prepare(\"select * from $this->table_post where `option_id` = %d AND `status` = 1  ORDER BY `id` $sort LIMIT %d\", $option_id, $count),\n            ARRAY_A\n        );\n    }\n\n\n\n    public function data_paging($page_number = 1, $per_page = 10, $customvar = 'total') {\n        $sql = \"SELECT * FROM $this->table_post\";\n\n        if (!empty($_REQUEST['option_id'])) {\n            $sql = $this->wpdb->prepare(\"$sql where option_id = %d\", frc_sanitize_text('option_id'));\n        }\n\n        if (in_array($customvar, array('1', '2', '3','4','5'))) {\n\t        $sql = $this->wpdb->prepare(\"$sql AND `status` = %d\", $customvar);\n        }\n\n        if (!empty($_REQUEST['orderby'])) {\n\t        $by = frc_sanitize_text('orderby');\n\t        $sort = !empty($_REQUEST['order']) ? frc_sanitize_text('order') : 'ASC';\n\t        $sort = strtoupper($sort) == 'ASC' ? 'ASC' : 'DESC';\n\t        $sql = $this->wpdb->prepare(\"$sql ORDER BY $by $sort\");\n        } else {\n            $sql .= ' ORDER BY id DESC';\n        }\n\n\t    $sql = $this->wpdb->prepare(\"$sql LIMIT %d OFFSET %d\", (int) $per_page, (int) (($page_number - 1) * $per_page));\n\n        return $this->wpdb->get_results($sql, 'ARRAY_A');\n    }\n\n\n    /**\n     * @param string $customvar\n     * @return null|string\n     */\n    public function record_count($customvar = 'total')\n    {\n        $sql = \"SELECT COUNT(*) FROM $this->table_post\";\n\n        if (!empty($_REQUEST['option_id'])) {\n            $sql = $this->wpdb->prepare(\"$sql where option_id = %d\", frc_sanitize_text('option_id'));\n        }\n\n        if (in_array($customvar, array('1', '2', '3','4','5'))) {\n            $sql = $this->wpdb->prepare(\"$sql AND status = %d\", $customvar);\n        }\n\n        return $this->wpdb->get_var($sql);\n    }\n\n\tpublic function update_successful_status( $id, $post )\n    {\n\t\treturn $this->wpdb->update( $this->table_post,\n\t\t\t[ 'post_id' => $post['ID'], 'status' => 3, 'updated_at' => current_time( 'mysql' ) ],\n\t\t\t[ 'id' => $id ], [ '%d', '%d', '%s' ], [ '%d' ]\n\t\t);\n\t}\n\n\n    /**\n     * @param $id\n     * @return false|int\n     */\n    public function delete($id)\n    {\n        return $this->wpdb->delete(\n            $this->table_post, array('id' => $id), array('%d')\n        );\n    }\n\n\n    /**\n     * @param $option_id\n     * @return false|int\n     */\n    public function delete_by_option($option_id)\n    {\n        return $this->wpdb->delete(\n            $this->table_post, array('option_id' => $option_id), array('%d')\n        );\n    }\n\n\n    /**\n     * @param $option_id\n     * @return array\n     */\n    public function statistical($option_id){\n        $statistical = [];\n        $allData = collect($this->wpdb->get_results(\n                $this->wpdb->prepare(\"select id, status, created_at, updated_at from $this->table_post where `option_id` = %d\", $option_id)\n        ));\n\n        $date = date('Y-m-d 00:00:00', strtotime(current_time('mysql')));\n        $statistical['all_count'] = $allData->count();\n        $statistical['release_count'] = $allData->where('status', '3')->count();\n        $statistical['not_release_count'] = $allData->where('status', '2')->count();\n        $statistical['to_day_release'] = $allData->where('updated_at', '>', $date)->where('status', 3)->count();\n        $statistical['to_day_collect'] = $allData->where('created_at', '>', $date)->whereIn('status', [2, 3])->count();\n        return $statistical;\n    }\n\n    public function data_automatic_release(){\n        $result = [];\n        foreach ((new FRC_Options())->options() as $option){\n            $data = $this->getDataByOption($option['id']);\n            foreach ($data as $article){\n                $re = $this->article_to_storage($article);\n                $result[] = $re;\n            }\n        }\n\n        return $result;\n    }\n\n\n    /**\n     * @return array\n     */\n    public function data_option_publish(){\n        $option_id = frc_sanitize_text('option_id', null);\n        $count = frc_sanitize_text('count', 1);\n        if ($option_id === null) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => 'option error!'];\n        }\n        $optionModel = new FRC_Options();\n        $option = $optionModel->option($option_id);\n        if (empty((array)json_decode($option['collect_release']))){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '失败, 请点击进入桶，配置默认发布配置后, 再使用快捷发布.'];\n        }\n\n        $data = $this->getDataByOption($option_id, $count);\n        foreach ($data as $item){\n            $this->article_to_storage($item);\n        }\n\n        return ['code' => FRC_ApiError::SUCCESS, 'msg' => '快捷发布完成.'];\n    }\n\n\n    /**\n     * @return array\n     */\n    public function data_publish_article(){\n        $release_id = frc_sanitize_text('release_id', null);\n        if ($release_id === null) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '发布的文章ID异常'];\n        }\n\n        $article = $this->id($release_id);\n        if (empty($article)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '亲, 文章异常!'];\n        }\n\n        return $this->article_to_storage($article);\n    }\n\n\n    /**\n     * @return array\n     */\n    public function data_preview_article(){\n        $release_id = frc_sanitize_text('release_id', null);\n        if ($release_id === null) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '发布的文章ID异常'];\n        }\n\n        $article = $this->id($release_id);\n        if (empty($article)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '亲, 文章异常!'];\n        }\n\n        $result = $this->article_to_storage($article, [\n                'post_status' => 'draft'\n        ]);\n\n        $result['data']['preview_url'] = get_permalink($result['data']['id']);\n        return $result;\n    }\n\n\n    /**\n     * @param $article\n     * @param array $custom_release_config\n     * @return array\n     */\n    public function article_to_storage($article, $custom_release_config = [])\n    {\n        if ($article['status'] != 2){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '发布失败, 文章状态不正确', 'data' => $article];\n        }\n\n        $optionModel = new FRC_Options();\n        $option = $optionModel->option($article['option_id']);\n\n        $release = json_decode($option['collect_release']);\n        if (empty($release) || $option['collect_release'] == '{}') {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '请保存发布配置后再发布', 'data' => $option['collect_release']];\n        }\n\n        $release_config = [];\n        $release_config['post_status'] = $release->status;\n        $release_config['post_user'] = $release->user[array_rand($release->user)];\n        $release_config['post_category'] = $release->category;\n\n        $release_config['thumbnail'] = $release->thumbnail == 'thumbnail1';\n        $release_config['image_download'] = $option['collect_image_download'];\n        $release_config['release_type'] = $release->type; //\n        $release_config['extension_field'] = $release->extension_field; //\n\n        if (!empty($custom_release_config)){\n            foreach ($custom_release_config as $key => $value){\n                $release_config[$key] = $value;\n            }\n        }\n\n        $post = array(\n            'post_title' => $article['title'],\n            'post_name' => $article['title'],\n            'post_content' => $article['content'],\n            'post_status' => $release_config['post_status'],\n            'post_author' => $release_config['post_user'],\n            'post_category' => $release_config['post_category'],\n            'tags_input' => '',\n            'post_type' => 'post',\n        );\n\n        $this->post_merge($post, $release_config);\n        if ($post_id = wp_insert_post($post)) {\n            $kitModel = new FRC_Kit();\n            $kitModel->kit_auto_tags($post_id);\n            $kitModel->kit_dynamic_fields($post_id);\n            $post = get_post($post_id, ARRAY_A);\n            $this->update_successful_status($article['id'], $post);\n            $this->update_post_meta($post['ID'], $release_config);\n            $this->uploadPicAttachment($post, $release_config);\n\n            return ['code' => FRC_ApiError::SUCCESS, 'msg' => '发布完成', 'data' => $post];\n        }\n\n        return ['code' => FRC_ApiError::FAIL, 'msg' => '发布失败', 'data' => $post];\n    }\n\n    public function data_history_wait_play()\n    {\n        $option_id = frc_sanitize_text('option_id', null);\n//        $cookie = frc_sanitize_text('cookie', null);\n        if ($option_id === null) return ['code' => FRC_ApiError::FAIL, 'msg' => '数据桶ID异常'];\n//        if ($cookie === null) return ['code' => FRC_ApiError::FAIL, 'msg' => '必须输入cookie'];\n        $model = new FRC_Data();\n        $result = $model->getWaitDataByOption($option_id);\n        $spider = new FRC_Spider();\n        if (count($result) > 0)\n        {\n            $info = $result[0];\n//            $info['link'] = str_replace(\"http://\", \"https://\", $info['link']);\n            $options = new FRC_Options();\n            $option = $options->lazy_person(\"微信\");\n//            $option[\"collect_cookie\"] = $cookie;\n            return $spider->response(\n                FRC_ApiError::SUCCESS,\n                //开始\n                $spider->single_spider($option, $info['link']));\n        }else{\n            return $spider->response(FRC_ApiError::ERR_PARAM,[],\"已经全部采集完毕\");\n        }\n\n    }\n\n    private function post_merge(&$post, $release_config){\n        $param = [];\n        if ($release_config['release_type'] === 'LightSNS') {\n            $param['post_type'] = 'post';\n            if ($release_config['extension_field'] === 'normal'){\n                $param['post_parent'] = 999999999;\n            }\n        } elseif ($release_config['release_type'] === '7b2') {\n            $param['post_type'] = 'post';\n        } else {\n            $param['post_type'] = $release_config['extension_field'] ? $release_config['extension_field'] : 'post';\n        }\n\n        $post = array_merge($post, $param);\n        return $post;\n    }\n\n    private function update_post_meta($post_id, $release_config){\n        if ($release_config['release_type'] === 'LightSNS') {\n            update_post_meta($post_id, 'post_type', $release_config['extension_field']);\n            if ($release_config['extension_field'] === 'normal'){\n                update_post_meta($post_id, 'last_comment_time', time());\n            }\n        } elseif ($release_config['release_type'] === '7b2') {\n            update_post_meta($post_id, 'b2_single_post_style', $release_config['extension_field']);\n        } else {\n\n        }\n    }\n\n    private function uploadPicAttachment($post, $release_config){\n        if ($release_config['image_download'] != 1) {\n            return ;\n        }\n\n        if (preg_match_all('/<img.*?src=\"(.*?)\".*?\\/?>/i', $post['post_content'],$matches)){\n            foreach ( (array)$matches[1] as $imageUrl ){\n                $wp_upload_dir = wp_upload_dir();\n                // 找到真实图片路径用于上传特色图片\n                $wp_upload_local_url_start = str_replace(site_url(), '', $wp_upload_dir['baseurl']);\n                $wp_upload_dir_base_dir = $wp_upload_dir['basedir'];\n                if (isset($wp_upload_dir['default']['baseurl'])){ // 关闭oss后 没有default\n                    $wp_upload_local_url_start = str_replace(site_url(), '', $wp_upload_dir['default']['baseurl']);\n                    $wp_upload_dir_base_dir = $wp_upload_dir['default']['basedir'];\n                }\n\n                if (startsWith($imageUrl, $wp_upload_local_url_start)) { // image in local\n                    $imagePath = str_replace($wp_upload_local_url_start, $wp_upload_dir_base_dir, $imageUrl);\n                } elseif (startsWith($imageUrl, $wp_upload_dir['baseurl'])) { // image in web/oss\n                    $imagePath = str_replace($wp_upload_dir['baseurl'], $wp_upload_dir['basedir'], $imageUrl);\n                } else {\n                    return ;\n                }\n\n                if (!empty($imagePath) && file_exists($imagePath)){\n                    $attachment = array(\n                        'guid'           => $imageUrl,\n                        'post_mime_type' => getimagesize($imagePath)['mime'],\n                        'post_title'     => basename($post['post_title']),\n                        'post_status'    => 'inherit'\n                    );\n                    $attach_id = wp_insert_attachment($attachment, $imagePath, $post['ID']);\n                    $attachment_data = wp_generate_attachment_metadata($attach_id, $imagePath);\n                    wp_update_attachment_metadata($attach_id, $attachment_data);\n                    if ($release_config['thumbnail']) {\n                        set_post_thumbnail($post['ID'], $attach_id);\n                        $release_config['thumbnail'] = false;\n                    }\n                }\n            }\n        }\n    }\n\n}\n\nif (!class_exists('WP_List_Table')) {\n    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');\n}\n\nclass FRC_Data_Detail_Table extends WP_List_Table\n{\n    /**\n     * Retrieve snippets data from the database\n     *\n     * @param int $per_page\n     * @param int $page_number\n     *\n     * @return mixed\n     */\n    public static function get_snippets($per_page = 10, $page_number = 1, $customvar = 'total')\n    {\n        $model = new FRC_Data();\n        $result = $model->data_paging($page_number, $per_page, $customvar);\n\n        return $result;\n    }\n\n    /**\n     * Delete a snipppet record.\n     * @param $id\n     * @return false|int\n     */\n    public function delete_snippet($id)\n    {\n        $model = new FRC_Data();\n        return $model->delete($id);\n    }\n\n    /**\n     * @param $id\n     * @return array\n     */\n    public function release_snippet($id)\n    {\n        $model = new FRC_Data();\n        $article = $model->id($id);\n        return $model->article_to_storage($article);\n    }\n\n    /**\n     * Activate a snipppet record.\n     *\n     * @param int $id snippet ID\n     */\n    public static function activate_snippet($id)\n    {\n\n    }\n\n    /**\n     * Deactivate a snipppet record.\n     *\n     * @param int $id snippet ID\n     */\n    public static function deactivate_snippet($id)\n    {\n\n    }\n\n    /**\n     * Returns the count of records in the database.\n     *\n     * @return null|string\n     */\n    public static function record_detail_count($customvar = 'total')\n    {\n        $model = new FRC_Data();\n        return $model->record_count($customvar);\n    }\n\n    /** Text displayed when no snippet data is available */\n    public function no_items()\n    {\n        esc_html_e('数据空空的, 请先开始采集之旅吧.', 'Fat Rat Collect');\n    }\n\n    /**\n     * Render a column when no column specific method exist.\n     *\n     * @param array $item\n     * @param string $column_name\n     *\n     * @return mixed\n     */\n    public function column_default($item, $column_name)\n    {\n        switch ($column_name) {\n            case 'status' :\n                switch ($item[$column_name]){\n                    case '1':\n                        return '<span class=\"label label-warning\">待采集</span>';\n                        break;\n                    case '2':\n                        return '<span class=\"label label-primary\">采集完成</span>';\n                        break;\n                    case '3':\n                        return '<span class=\"label label-success\">已发布</span>';\n                        break;\n                    case '5':\n                        return '<span class=\"label label-danger\">已失败</span>';\n                        break;\n                }\n                break;\n            case 'cover' :\n                return sprintf(\"<img src='%s' />\", $item[$column_name]);\n                break;\n            case 'link' :\n                return sprintf(\"<a href='%s' target='_blank'>%s</a>\", $item[$column_name], $item[$column_name]);\n                break;\n            case 'content':\n                return esc_html(mb_substr($item[$column_name], 0, 30) . ' ...');\n                break;\n            case 'post_id':\n                return sprintf(\"<a href='%s' target='_blank'>%s</a>\", get_permalink($item[$column_name]), $item[$column_name]);\n                break;\n            case 'title':\n                $title = '<strong>' . $item['title'] . '</strong>';\n                if ($item['status'] != 2){\n                    return $title;\n                }\n                $actions = array(\n                    '发布' => sprintf(\"<a href='javascript:;'><span class='publish-article' data-value='%s'>%s</span></a>\", $item['id'], esc_html__('发布', 'Fat Rat Collect')),\n                    '预览' => sprintf(\"<a href='javascript:;'><span class='preview-article' data-value='%s'>%s</span></a>\", $item['id'], esc_html__('预览', 'Fat Rat Collect')),\n                );\n                return $title . $this->row_actions( $actions );\n                break;\n            default:\n                return esc_html($item[$column_name]);\n                break;\n        }\n    }\n\n    /**\n     * Render the bulk edit checkbox\n     *\n     * @param array $item\n     *\n     * @return string\n     */\n    function column_cb($item)\n    {\n        return sprintf(\n            '<input type=\"checkbox\" name=\"snippets[]\" value=\"%s\" />', $item['id']\n        );\n    }\n\n    /**\n     * Method for name column\n     *\n     * @param array $item an array of DB data\n     *\n     * @return string\n     */\n    function column_name($item)\n    {\n\n    }\n\n    /**\n     *  Associative array of columns\n     *\n     * @return array\n     */\n    function get_columns()\n    {\n        $columns = array(\n            'cb' => '<input type=\"checkbox\" />',\n            'id' => esc_html__('ID', 'Fat Rat Collect'),\n            'status' => esc_html__('状态', 'Fat Rat Collect'),\n            'title' => esc_html__('Title', 'Fat Rat Collect'),\n            'link' => esc_html__('原文地址', 'Fat Rat Collect'),\n            'content' => esc_html__('内容', 'Fat Rat Collect'),\n            'post_id' => esc_html__('发布后wp ID', 'Fat Rat Collect'),\n            'message' => esc_html__('Message', 'Fat Rat Collect'),\n            'created_at' => esc_html__('采集时间', 'Fat Rat Collect'),\n            'updated_at' => esc_html__('最后修改时间', 'Fat Rat Collect'),\n        );\n\n        return $columns;\n    }\n\n    /**\n     * Columns to make sortable.\n     *\n     * @return array\n     */\n    public function get_sortable_columns()\n    {\n\n        return array(\n            'id' => array('id', false),\n            'status' => array('status', true),\n        );\n    }\n\n    /**\n     * Returns an associative array containing the bulk action\n     *\n     * @return array\n     */\n    public function get_bulk_actions()\n    {\n        return array(\n            'bulk-release' => esc_html__('批量发布数据', 'Fat Rat Collect'),\n            'bulk-delete' => esc_html__('删除(删除后滤重失效)', 'Fat Rat Collect'),\n        );\n    }\n\n    /**\n     * Handles data query and filter, sorting, and pagination.\n     */\n    public function prepare_items()\n    {\n\n        $columns = $this->get_columns();\n        $hidden = array();\n        $sortable = $this->get_sortable_columns();\n\n        //Retrieve $customvar for use in query to get items.\n        $customvar = frc_sanitize_text('customvar', 'total');\n        $this->_column_headers = array($columns, $hidden, $sortable);\n\n        /** Process bulk action */\n        $this->process_bulk_action();\n        $this->views();\n        // $per_page = $this->get_items_per_page('snippets_per_page', 10);\n        $per_page = frc_sanitize_text('snippets_per_page', 10);\n        $current_page = $this->get_pagenum();\n        $current = frc_sanitize_text('customvar', 'total');\n\n        $total_items = self::record_detail_count($current);\n\n        $this->set_pagination_args(array(\n            'total_items' => $total_items,\n            'per_page' => $per_page,\n        ));\n\n        $this->items = self::get_snippets($per_page, $current_page, $customvar);\n    }\n\n\tpublic function get_views()\n\t{\n\t\t$views = array();\n\n\t\t// 对 customvar 参数进行安全处理\n\t\t$current = sanitize_text_field(frc_sanitize_text('customvar', 'total'));\n\n\t\t// 构建所有数据视图\n\t\t$class = ('total' === $current) ? ' class=\"current\"' : '';\n\t\t$total_url = esc_url(remove_query_arg('customvar'));\n\t\t$views['total'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$total_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('所有数据', 'Fat Rat Collect'),\n\t\t\t$this->record_detail_count()\n\t\t);\n\n\t\t// 构建待采集视图\n\t\t$foo_url = esc_url(add_query_arg('customvar', '1'));\n\t\t$class = ('1' === $current) ? ' class=\"current\"' : '';\n\t\t$waitCollectCount = $this->record_detail_count('1');\n\t\t$views['1'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$foo_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('待采集', 'Fat Rat Collect'),\n\t\t\t$waitCollectCount\n\t\t);\n\n\t\t// 如果有待采集数据，添加按钮\n\t\tif ($waitCollectCount > 0) {\n\t\t\t$views['1'] .= sprintf(\n\t\t\t\t'<input type=\"button\" id=\"wp-frc-data-play\" data-option_id=\"%s\" class=\"button action\" value=\"%s\">',\n\t\t\t\tesc_attr(frc_sanitize_text('option_id')),\n\t\t\t\tesc_attr__('play', 'Fat Rat Collect')\n\t\t\t);\n\t\t}\n\n\t\t// 构建采集完成视图\n\t\t$bar_url = esc_url(add_query_arg('customvar', '2'));\n\t\t$class = ('2' === $current) ? ' class=\"current\"' : '';\n\t\t$views['2'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$bar_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('采集完成', 'Fat Rat Collect'),\n\t\t\t$this->record_detail_count('2')\n\t\t);\n\n\t\t// 构建已发布视图\n\t\t$all_url = esc_url(add_query_arg('customvar', '3'));\n\t\t$class = ('3' === $current) ? ' class=\"current\"' : '';\n\t\t$views['3'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$all_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('已发布', 'Fat Rat Collect'),\n\t\t\t$this->record_detail_count('3')\n\t\t);\n\n\t\t// 构建已失败视图\n\t\t$all_url = esc_url(add_query_arg('customvar', '5'));\n\t\t$class = ('5' === $current) ? ' class=\"current\"' : '';\n\t\t$views['5'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$all_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('已失败', 'Fat Rat Collect'),\n\t\t\t$this->record_detail_count('5')\n\t\t);\n\n\t\treturn $views;\n\t}\n\n\tpublic function process_bulk_action()\n    {\n        // If the delete bulk action is triggered\n        if (\n            ( isset( $_POST['action'] ) && 'bulk-release' === $_POST['action'] ) ||\n            ( isset( $_POST['action2'] ) && 'bulk-release' === $_POST['action2'] )\n        ) {\n            $snippets_ids = frc_sanitize_array('snippets');\n\n            foreach ( $snippets_ids as $id ) {\n                $this->release_snippet( $id );\n            }\n\n            return;\n        }\n        if (\n            ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) ||\n            ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] )\n        ) {\n            $delete_ids = frc_sanitize_array('snippets');\n\n            // loop over the array of record IDs and delete them\n            foreach ( $delete_ids as $id ) {\n                $this->delete_snippet( $id );\n            }\n\n            return;\n        }\n    }\n}\n\nfunction frc_data_detail()\n{\n    if (!isset($_REQUEST['option_id'])){\n        $url = admin_url('admin.php?page=frc-data');\n        _e(\"<script type='text/javascript'>window.location.href = '{$url}';</script>\");\n        return ;\n    }\n    $optionModel = new FRC_Options();\n    $option = $optionModel->option(frc_sanitize_text('option_id'));\n    $release = json_decode($option['collect_release']);\n    $categorys = get_categories(array('hide_empty' => false, 'order' => 'ASC', 'orderby' => 'id'));\n    $users = get_users(array(\n        'fields' => array('ID', 'user_nicename', 'display_name')\n    ));\n    $snippet_obj = new FRC_Data_Detail_Table();\n    ?>\n\n    <div class=\"wrap\">\n        <h2>\n            <img width=\"40\" class=\"request—loading\" src=\"<?php esc_attr_e(plugin_dir_url(dirname(__FILE__)) . 'images/fat-rat-128x128.png'); ?>\"/>\n            <?php esc_html_e(' 数据列表', 'Fat Rat Collect'); ?>\n            <?php if (!empty(get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP))) { ?>\n                <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png') ?>\" />\n            <?php } ?>\n            <a href=\"<?php esc_attr_e(admin_url( 'admin.php?page=frc-data' )); ?>\"><label class=\"label label-warning float-end\">返回数据桶</label></a>\n        </h2>\n        <span><?php _e($option['collect_name'], 'Fat Rat Collect'); ?></span>\n        <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n        <input type=\"hidden\" hidden id=\"success_redirect_url\" value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-data-detail&option_id='.$option['id'])); ?>\">\n        <input type=\"hidden\" hidden id=\"current_option_id\" value=\"<?php esc_attr_e($option['id']) ?>\">\n\t    <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n        <div class=\"row\">\n                <div class=\"col-10\">\n                    <form method=\"post\">\n                        <?php\n                        $snippet_obj->prepare_items();\n                        $snippet_obj->display();\n                        ?>\n                    </form>\n                </div>\n                <div class=\"col-2\">\n                    <?php\n                    if (!get_object_vars($release)){\n                        _e('<h4 style=\"color: #4285f4\">第一次来数据桶, 要想发布文章, 点击下方保存发布配置，可快速保存默认发布配置:</h4>');\n                    }\n                    _e( '<p>' );\n                    _e( '<img width=\"60\" src=\"'.plugin_dir_url(dirname(__FILE__)).'images/fat-rat-256x256.png'.'\" />' );\n                    _e( '<img width=\"60\" src=\"'.plugin_dir_url(dirname(__FILE__)).'images/fat-rat-256x256.png'.'\" />' );\n                    _e( '<img width=\"60\" src=\"'.plugin_dir_url(dirname(__FILE__)).'images/fat-rat-256x256.png'.'\" />' );\n                    _e( '</p>' );\n                    ?>\n                    <br />\n                    <p><input type=\"button\" class=\"button button-primary\" id=\"save-release-option\" value=\"保存发布配置\" /></p>\n                    <p class=\"p-tips-style\">保存配置生效后, 用于快捷发布, 自动发布, 和其他地方发布</p>\n                    <hr />\n                    <?php require_once(plugin_dir_path(__DIR__) . 'views/release-type.php'); ?>\n                    <h5>设置文章发布状态:</h5>\n                    <ul>\n                        <?php foreach ([\n                                           'publish' => '发布',\n                                           'pending' => '待审核',\n                                           'draft' => '草稿',\n                                       ] as $val => $title): ?>\n                            <li><input type=\"radio\" value=\"<?php esc_attr_e($val, 'publish') ?>\" name=\"post_status\" <?php if (isset($release->status) && $val == $release->status) esc_attr_e('checked'); ?>> <?php esc_html_e($title, 'Fat Rat Collect') ?></li>\n                        <?php endforeach; ?>\n                    </ul>\n                    <hr />\n                    <h5>设置特色图片(封面图):</h5>\n                    <ul>\n                        <li>\n                            <input type=\"radio\" value=\"thumbnail1\" name=\"post_thumbnail\" <?php if (isset($release->thumbnail) && 'thumbnail1' == $release->thumbnail) esc_attr_e('checked'); ?> />\n                            <?php _e('使用正文第一张图', 'Fat Rat Collect') ?>\n                        </li>\n                        <li>\n                            <input type=\"radio\" value=\"thumbnail2\" name=\"post_thumbnail\" <?php if (isset($release->thumbnail) && 'thumbnail2' == $release->thumbnail) esc_attr_e('checked'); ?> />\n                            <?php _e('不需要特色图片', 'Fat Rat Collect') ?>\n                        </li>\n                    </ul>\n                    <hr />\n                    <h5>设置发布分类:</h5>\n                    <ul class=\"checkbox_post_category\">\n                        <?php foreach ($categorys as $category): ?>\n                            <li>\n                                <?php\n                                if ($category->parent != 0){\n                                    esc_html_e('&nbsp;&nbsp;');\n                                } ?>\n                                <input type=\"checkbox\" name=\"post_category[]\" value=\"<?php esc_attr_e($category->cat_ID); ?>\" <?php if (isset($release->category) && in_array($category->cat_ID, $release->category)){ esc_attr_e('checked'); } ?>>&nbsp;<?php _e($category->cat_name, 'Fat Rat Collect'); ?></li>\n                        <?php endforeach; ?>\n                    </ul>\n                    <hr />\n                    <h5>设置发布作者: (多选随机)</h5>\n                    <ul class=\"checkbox_post_user\">\n                        <?php foreach ($users as $user): ?>\n                            <li><input type=\"checkbox\" name=\"post_user[]\" value=\"<?php esc_attr_e($user->ID); ?>\" <?php if (isset($release->user) && in_array($user->ID, $release->user)){ esc_attr_e('checked'); } ?>>&nbsp;<?php _e($user->user_nicename . '(' . $user->display_name . ')', 'Fat Rat Collect'); ?></li>\n                        <?php endforeach; ?>\n                    </ul>\n                    <br />\n                    <br />\n                    <div class=\"fixed\"><img width=\"150\" src=\"<?php esc_attr_e(plugin_dir_url(dirname(__FILE__)).'images/fat-rat-256x256.png');  ?>\" /></div>\n                </div>\n            </div>\n    </div>\n    <?php\n}"
  },
  {
    "path": "includes/fatrat-data.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2018年12月30日 02:24\n */\n\nif (!class_exists('WP_List_Table')) {\n    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');\n}\n\nclass FRC_Data_List_Table extends WP_List_Table\n{\n    /**\n     * Retrieve snippets data from the database\n     *\n     * @param int $per_page\n     * @param int $page_number\n     *\n     * @return mixed\n     */\n    public static function get_snippets($per_page = 10, $page_number = 1, $customvar = 'total')\n    {\n        $model = new FRC_Options();\n        $dataModel = new FRC_Data();\n        $result = $model->options_paging($page_number, $per_page, $customvar);\n\n        return collect($result)->map(function ($data) use ($model, $dataModel) {\n            $option = $model->option($data['id']);\n\n            $category = '未设置';\n            if ($release = json_decode($option['collect_release'])){\n                if (isset($release->category)){\n                    $category = '';\n                    foreach ($release->category as $item) {\n                        $category .= get_cat_name($item).',';\n                    }\n                    $category = rtrim($category, ',');\n                }\n            }\n\n            $data['collect_release_categories'] = $category;\n            $statistical = $dataModel->statistical($data['id']);\n            $data['data_all_count'] = $statistical['all_count'];\n            $data['data_release_count'] = $statistical['release_count'];\n            $data['data_not_release_count'] = $statistical['not_release_count'];\n            $data['data_to_day_release'] = $statistical['to_day_release'];\n            $data['data_to_day_collect'] = $statistical['to_day_collect'];\n            return $data;\n        });\n\n    }\n\n    /**\n     * Delete a snipppet record.\n     * @param $id\n     * @return false|int\n     */\n    public function delete_snippet($id)\n    {\n        $model = new FRC_Options();\n        return $model->delete($id);\n    }\n\n    /**\n     * Activate a snipppet record.\n     *\n     * @param int $id snippet ID\n     */\n    public static function activate_snippet($id)\n    {\n\n    }\n\n    /**\n     * Deactivate a snipppet record.\n     *\n     * @param int $id snippet ID\n     */\n    public static function deactivate_snippet($id)\n    {\n\n    }\n\n    /**\n     * Returns the count of records in the database.\n     *\n     * @return null|string\n     */\n    public static function record_count($customvar = 'total')\n    {\n        $model = new FRC_Options();\n        return $model->record_count($customvar);\n    }\n\n    /** Text displayed when no snippet data is available */\n    public function no_items()\n    {\n        esc_html_e('配置空空的, 请创建采集配置开始旅程吧', 'Fat Rat Collect');\n    }\n\n    /**\n     * Render a column when no column specific method exist.\n     *\n     * @param array $item\n     * @param string $column_name\n     *\n     * @return mixed\n     */\n    public function column_default($item, $column_name)\n    {\n        switch ($column_name) {\n//            case 'data_to_day_collect':\n//                return '<span class=\"label label-info\">'.$item[$column_name].'</span>';\n//                break;\n//            case 'data_not_release_count':\n//                return '<span class=\"label label-default\">'.$item[$column_name].'</span>';\n//                break;\n//            case 'data_release_count':\n//                return '<span class=\"label label-warning\">'.$item[$column_name].'</span>';\n//                break;\n//            case 'data_all_count':\n//                return '<span class=\"label label-primary\">'.$item[$column_name].'</span>';\n//                break;\n            case 'collect_name':\n                $title = '<strong>' . $item['collect_name'] . '</strong>';\n                $actions = array(\n                    '进入桶' => sprintf(\"<a href='%s'>%s</a>\", admin_url('admin.php?page=frc-data-detail&option_id=' . $item['id']), esc_html__('进入桶', 'Fat Rat Collect')),\n                    '快捷发布' => sprintf(\"<a href='javascript:;'><span class='quick-release-option-button' data-value='%s'>%s</span></a>\", $item['id'], esc_html__('快捷发布', 'Fat Rat Collect')),\n                );\n                return $title . $this->row_actions( $actions );\n                break;\n            default:\n                return esc_html($item[$column_name]);\n                break;\n        }\n    }\n\n    /**\n     * Render the bulk edit checkbox\n     *\n     * @param array $item\n     *\n     * @return string\n     */\n    function column_cb($item)\n    {\n        return sprintf(\n            '<input type=\"checkbox\" name=\"snippets[]\" value=\"%s\" />', $item['id']\n        );\n    }\n\n    /**\n     * Method for name column\n     *\n     * @param array $item an array of DB data\n     *\n     * @return string\n     */\n    function column_name($item)\n    {\n\n    }\n\n    /**\n     *  Associative array of columns\n     *\n     * @return array\n     */\n    function get_columns()\n    {\n        $columns = array(\n            'cb' => '<input type=\"checkbox\" />',\n            'id' => esc_html__('ID', 'Fat Rat Collect'),\n            'collect_name' => esc_html__('数据桶名称', 'Fat Rat Collect'),\n            'collect_release_categories' => esc_html__('发布分类', 'Fat Rat Collect'),\n            'data_to_day_release' => esc_html__('今日发布', 'Fat Rat Collect'),\n            'data_to_day_collect' => esc_html__('今日采集', 'Fat Rat Collect'),\n            'data_not_release_count' => esc_html__('未发布总量', 'Fat Rat Collect'),\n            'data_release_count' => esc_html__('已发布总量', 'Fat Rat Collect'),\n            'data_all_count' => esc_html__('桶数据总量', 'Fat Rat Collect'),\n            'created_at' => esc_html__('桶创建时间', 'Fat Rat Collect'),\n        );\n\n        return $columns;\n    }\n\n    /**\n     * Columns to make sortable.\n     *\n     * @return array\n     */\n    public function get_sortable_columns()\n    {\n\n        return array(\n            'id' => array('id', false),\n        );\n    }\n\n    /**\n     * Returns an associative array containing the bulk action\n     *\n     * @return array\n     */\n    public function get_bulk_actions()\n    {\n\n        return array(\n            'bulk-quick-release' => esc_html__('批量快捷发布(待开发)', 'Fat Rat Collect'),\n        );\n    }\n\n    /**\n     * Handles data query and filter, sorting, and pagination.\n     */\n    public function prepare_items()\n    {\n\n        $columns = $this->get_columns();\n        $hidden = array();\n        $sortable = $this->get_sortable_columns();\n\n        //Retrieve $customvar for use in query to get items.\n        $customvar = frc_sanitize_text('customvar', 'total');\n        $this->_column_headers = array($columns, $hidden, $sortable);\n\n        /** Process bulk action */\n        $this->process_bulk_action();\n        $this->views();\n        $per_page = $this->get_items_per_page('snippets_per_page', 10);\n        $current_page = $this->get_pagenum();\n        $total_items = self::record_count();\n\n        $this->set_pagination_args(array(\n            'total_items' => $total_items,\n            'per_page' => $per_page,\n        ));\n\n        $this->items = self::get_snippets($per_page, $current_page, $customvar);\n    }\n\n\tpublic function get_views()\n\t{\n\t\t$views = array();\n\n\t\t// 确保对 'customvar' 的输入进行安全处理\n\t\t$current = sanitize_text_field(frc_sanitize_text('customvar', 'total'));\n\n\t\t// 构建总计视图\n\t\t$class = ('total' === $current) ? ' class=\"current\"' : '';\n\t\t$total_url = esc_url(remove_query_arg('customvar'));\n\t\t$views['total'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$total_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('全部配置', 'Fat Rat Collect'),\n\t\t\t$this->record_count()\n\t\t);\n\n\t\t// 构建列表采集视图\n\t\t$foo_url = esc_url(add_query_arg('customvar', 'list'));\n\t\t$class = ('list' === $current) ? ' class=\"current\"' : '';\n\t\t$views['list'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$foo_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('列表采集', 'Fat Rat Collect'),\n\t\t\t$this->record_count('list')\n\t\t);\n\n\t\t// 构建详情采集视图\n\t\t$bar_url = esc_url(add_query_arg('customvar', 'single'));\n\t\t$class = ('single' === $current) ? ' class=\"current\"' : '';\n\t\t$views['single'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$bar_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('详情采集', 'Fat Rat Collect'),\n\t\t\t$this->record_count('single')\n\t\t);\n\n\t\t// 构建全站采集视图（如果启用）\n\t\tif (get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT)) {\n\t\t\t$all_url = esc_url(add_query_arg('customvar', 'all'));\n\t\t\t$class = ('all' === $current) ? ' class=\"current\"' : '';\n\t\t\t$views['all'] = sprintf(\n\t\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t\t$all_url,\n\t\t\t\tesc_attr($class),\n\t\t\t\tesc_html__('全站采集', 'Fat Rat Collect'),\n\t\t\t\t$this->record_count('all')\n\t\t\t);\n\t\t}\n\n\t\treturn $views;\n\t}\n\n\tpublic function process_bulk_action()\n    {\n        // If the delete bulk action is triggered\n//        if (\n//            ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) ||\n//            ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] )\n//        ) {\n//            $delete_ids = esc_sql( $_POST['snippets'] );\n//\n//            // loop over the array of record IDs and delete them\n//            foreach ( $delete_ids as $id ) {\n//                $this->delete_snippet( $id );\n//            }\n//\n//            return;\n//        }\n    }\n}\n\nfunction frc_data_list()\n{\n    $snippet_obj = new FRC_Data_List_Table();\n    ?>\n\n    <div class=\"wrap\">\n        <h1>\n            <?php esc_html_e('数据桶控制中心', 'Fat Rat Collect') ?>\n            <?php if (!empty(get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP))) { ?>\n                <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png') ?>\" />\n            <?php } ?>\n        </h1>\n        <div><span style=\"color: #4285f4;\"><?php _e((new FRC_Validation())->announcement('notice-data')); ?></span></div>\n        <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n        <input type=\"hidden\" hidden id=\"success_redirect_url\" value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-data')); ?>\">\n\t    <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n\n        <form method=\"post\">\n            <?php\n            $snippet_obj->prepare_items();\n            $snippet_obj->display();\n            ?>\n        </form>\n    </div>\n    <?php\n}\n"
  },
  {
    "path": "includes/fatrat-debugging.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: FatRat\n * @CreateTime: 2020年04月11日 12:25\n */\n\nfunction frc_debugging(){\n    ?>\n\n    <div class=\"wrap\">\n        <h1><?php _e('胖鼠调试台', 'Fat Rat Collect') ?></h1>\n        <p></p>\n        <p style=\"color: #00b300\"><?php _e((new FRC_Validation())->announcement('notice-debug')); ?></p>\n\n        <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n        <input type=\"hidden\" hidden id=\"success_redirect_url\" value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-debugging')); ?>\">\n\t    <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n\n        <table class='form-table debug-table'>\n            <tr>\n                <th>地址:</th>\n                <td><input size=\"50\" name=\"debug_url\"/><p style=\"font-size: 12px; color: #cca154\">此处可以填写你要爬取的地址. 列表页/详情页 地址 均可</p></td>\n            </tr>\n            <tr>\n                <th>编码处理:</th>\n                <td>\n                    <input type=\"radio\" checked name=\"debug_remove_head\" value=\"1\"> 自动识别(推荐)\n                    <input type=\"radio\" name=\"debug_remove_head\" value=\"2\"> 删HEAD(非UTF-8编码推荐)\n                    <input type=\"radio\" name=\"debug_remove_head\" value=\"3\"> <span style=\"color: #db9925\">强制转换(终方)</span>\n                </td>\n            </tr>\n            <?php if (get_option(FRC_Validation::FRC_VALIDATION_RENDERING)) { ?>\n            <tr>\n                <th>采集方式:</th>\n                <td>\n                    <input type=\"radio\" name=\"debug_rendering\" value=\"1\" checked >\n                    静态渲染\n                    <input type=\"radio\" name=\"debug_rendering\" value=\"2\">\n                    动态渲染\n                </td>\n            </tr>\n            <?php } ?>\n            <tr>\n                <th>范围:</th>\n                <td><input size=\"50\" name=\"debug_range\"/>\n                    <p style=\"font-size: 12px; color: #cca154\">填写Html标签的 class 或者 id (Jquery语法) <a href=\"https://www.fatrat.cn/docs/v2/core-rules\" target=\"_blank\">参考</a></p></td></td>\n            </tr>\n            <tr>\n                <th>采集规则:</th>\n                <td>\n                    &nbsp;&nbsp;&nbsp;<span style=\"color: #CC6633\">规则名&nbsp;&nbsp;- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JQuery选择器 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n                    &nbsp;&nbsp;&nbsp;- &nbsp;属性 &nbsp; - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;标签过滤: 空格分割</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a\n                        href=\"https://www.fatrat.cn/docs/v2/core-rules\" target='_blank'>参考</a> | <a\n                        href=\"http://jquery.cuishifeng.cn/\" target='_blank'>语法</a><br/>\n                    <input type=\"text\" size=\"6\" value=\"\" name=\"collect_debug_rule_a\"/>-<input type=\"text\" size=\"20\"\n                                                                                              value=\"<?php esc_attr_e(isset($option) ? $rule_link['b'] : ''); ?>\"\n                                                                                              name=\"collect_debug_rule_b\"/>-<input\n                        type=\"text\" size=\"4\" value=\"<?php esc_attr_e(isset($option) ? $rule_link['c'] : ''); ?>\"\n                        name=\"collect_debug_rule_c\"/>-<input type=\"text\" size=\"40\"\n                                                             value=\"<?php esc_attr_e(isset($option) ? $rule_link['d'] : ''); ?>\"\n                                                             name=\"collect_debug_rule_d\"/>*\n                    <p style=\"color: #838383;font-size: 12px;\">内容过滤Jquery常用语法: :eq(等于) :gt(大于) :lt(小于) :first(第一个) :last(最后一个) :even(偶数) :odd(奇数) <a href=\"http://jquery.cuishifeng.cn/element.html\" target=\"_blank\">更多</a></p>\n                </td>\n            </tr>\n            <tr>\n                <th colspan=\"2\">\n                    <input class=\"button button-primary\" type=\"button\" id=\"debug-option\" value=\"请求调试\"/>\n                    <p></p>\n                    <p>首先, 打开开发者工具, Chrome浏览器控制台打开方法: 右键->检查->console, 其他浏览器大同小异. </p>\n                    <p>点击debugging后请看控制台Console里面的数据, 文字教程, 视频教程中 均有介绍如何使用, 照葫芦画瓢.</p>\n                    <p>视频教程, 文字教程已经写的很详细了, 如果你没有耐心花30分钟熟悉胖鼠、可在插件管理->选择胖鼠->卸载 = - =! / 或者来骚扰下作者 <a target=\"_blank\" href=\"https://www.fatrat.cn/docs/v2/write-rules\">代写</a></p>\n                    <p class=\"p-tips-style\">采集中心所有采集均支持debugging模式哦、最后如果胖鼠采集帮助到你, 请支持一下开源作品 插件<a target=\"_blank\" href=\"https://wordpress.org/support/plugin/fat-rat-collect/reviews\">五星好评支持</a></p>\n                </th>\n            </tr>\n            <tr>\n                <td colspan=\"2\"><?php _e((new FRC_Validation())->getAppreciatesHtml(7)); ?></td>\n            </tr>\n        </table>\n    </div>\n    <?php\n}"
  },
  {
    "path": "includes/fatrat-kit.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2020年4月1日\n */\n\nclass FRC_Kit{\n\n    public function kit_image_path($file){\n        return plugin_dir_url(dirname(__FILE__)).'images/' . $file;\n    }\n\n    public function kit_automatic_save_pic($postID){\n        if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)\n            || (!current_user_can('edit_post', $postID))) {\n            return;\n        }\n        remove_action('publish_post', 'frc_automatic_save_pic');\n        $post_content = get_post($postID)->post_content;\n        // 逻辑\n\n        add_action('publish_post', 'frc_automatic_save_pic');\n    }\n\n    public function kit_auto_tags($postID){\n        $result = get_option(FRC_Validation::FRC_VALIDATION_AUTO_TAGS);\n        if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || empty($result) || @json_decode($result)->switch != 'open') {\n            return;\n        }\n\n        $post_content = get_post($postID)->post_content;\n        $add_tag_link = get_the_tags($postID);\n        if (!$add_tag_link){\n            collect(get_tags( array('hide_empty' => false) ))->map(function ($tag) use ($postID, &$post_content){\n                if ( stristr($post_content,$tag->name) !== false) {\n                    wp_set_post_tags( $postID, $tag->name, true );\n                }\n            });\n        }\n    }\n\n\n    public function kit_dynamic_fields($postID){\n        $result = get_option(FRC_Validation::FRC_VALIDATION_DYNAMIC_FIELDS);\n        if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || empty($result) || @json_decode($result)->switch != 'open') {\n            return;\n        }\n\n        $content = get_post($postID)->post_content;\n\n        if (strpos( $content, '<blockquote' ) !== false || strpos( $content, '</blockquote>' ) !== false){\n            return;\n        }\n\n        $cats = collect(get_the_category($postID));\n        if ($cats->isEmpty()) {\n            return ;\n        }\n        $cat_ids = $cats->pluck('term_id');\n        $args = array('orderby' => 'rand','showposts' => 1,'cat' => $cat_ids->implode(','), 'date_query' => array(\n            'column' => 'post_date',\n            'after' => date('Y-m-d H:i:s', strtotime(current_time('mysql'))-(3600*24*57)),\n            'before' => current_time('mysql')\n        ));\n\n        $query_posts = new WP_Query();\n        $posts_data = $query_posts->query($args);\n\n        if (empty($posts_data)) {\n            return ;\n        }\n\n        /*\n        if (isset($posts_data[0]) && $previous_post = $posts_data[0]){\n            $link = get_permalink($previous_post->ID);\n            $pre_string = sprintf('<blockquote style=\"background: #F5F5F5; font-size: 10px;\"><a href=\"%s\" style=\"text-decoration: none\"><span style=\"color: #929292;\">%s</span><p>%s</p></a></blockquote>', $link, $previous_post->post_title, wp_trim_words($previous_post->post_content, 130));\n            $content = $pre_string.$content;\n        }\n         */\n\n        if (isset($posts_data[0]) && $next_post = $posts_data[0]){\n            $link = get_permalink($next_post->ID);\n            $next_string = sprintf('<blockquote style=\"background: #F5F5F5; font-size: 10px;\"><a href=\"%s\" style=\"text-decoration: none\"><span style=\"color: #929292;\">相关推荐: %s</span><p>%s</p></a></blockquote>', $link, $next_post->post_title, wp_trim_words($next_post->post_content, 130));\n            $content = $content.$next_string;\n        }\n\n        wp_update_post(array('ID' => $postID, 'post_content' => $content));\n    }\n}\n\nif (!function_exists(\"frc_image\")) {\n    /**\n     * @param $file\n     * @return string\n     */\n    function frc_image($file){\n        $model = new FRC_Kit();\n        esc_html_e($model->kit_image_path($file));\n    }\n}\n\nfunction frc_auto_task($postID){\n    $model = new FRC_Kit();\n    $model->kit_auto_tags($postID);\n    $model->kit_dynamic_fields($postID);\n}\nadd_action('publish_post', 'frc_auto_task');\n\n$result = get_option(FRC_Validation::FRC_VALIDATION_INNER_CHAIN);\nif ($result && @json_decode($result)->switch === 'open'){\n    function frc_inner_chain( $post_content ) {\n        $config = json_decode(get_option(FRC_Validation::FRC_VALIDATION_INNER_CHAIN));\n        $limit = isset($config->limit) ? $config->limit : 1;\n\n        collect(get_tags( array('hide_empty' => false) ))->map(function ($tag) use (&$post_content, $limit){\n            if ( stristr($post_content,$tag->name) !== false) {\n\n                $link = get_tag_link($tag->term_id);\n                $keyword = stripslashes($tag->name);\n                $url = sprintf('<a href=\"%s\" target=\"_blank\" title=\"%s\">%s</a>', $link, $keyword, $keyword);\n                $regEx = '\\'(?!((<.*?)|(<a.*?)))('. $keyword . ')(?!(([^<>]*?)>)|([^>]*?</a>))\\'s';\n                $post_content = preg_replace($regEx, $url, $post_content, $limit);\n            }\n        });\n\n        return $post_content;\n\n    }\n    add_filter('the_content','frc_inner_chain');\n}\n\nfunction frc_kit(){\n    $frc_validation_tags = get_option(FRC_Validation::FRC_VALIDATION_AUTO_TAGS);\n    $frc_validation_chain = get_option(FRC_Validation::FRC_VALIDATION_INNER_CHAIN);\n    $frc_validation_dynamic = get_option(FRC_Validation::FRC_VALIDATION_DYNAMIC_FIELDS);\n    $frc_validation_automatic_save_pic = get_option(FRC_Validation::FRC_VALIDATION_AUTOMATIC_SAVE_PIC);\n    $frc_validation_release_control = get_option(FRC_Validation::FRC_VALIDATION_RELEASE_CONTROL);\n    $frc_validation_insert_keyword = get_option(FRC_Validation::FRC_VALIDATION_INSERT_KEYWORD);\n    $frc_validation_wechat_history = get_option(FRC_Validation::FRC_VALIDATION_WECHAT_HISTORY);\n    $frc_validation_sponsorship = get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP);\n    $frc_wp_schedules = wp_get_schedules();\n    array_multisort(array_column($frc_wp_schedules, 'interval'), SORT_ASC, $frc_wp_schedules);\n    ?>\n    <div class=\"wrap\">\n        <h1><?php esc_html_e('胖鼠工具箱', 'Fat Rat Collect') ?>\n            <img width=\"80\" class=\"float-end\" src=\"<?php frc_image('fat-rat-kit-256x256.png') ?>\">\n        </h1>\n        <p></p>\n\n        <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n        <input type=\"hidden\" hidden id=\"success_redirect_url\" value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-kit')); ?>\">\n\t    <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n\n        <!--        增加删除采集文章是否删除图片-->\n        <!--        增加删除已发布的文章是否删除附件-->\n        <nav>\n            <div class=\"nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\n                <?php foreach([\n                                  ['title' => '胖鼠工具箱', 'anchor' => '#kit', 'permissions' => $frc_validation_sponsorship],\n                                  ['title' => '自动采集', 'anchor' => '#autospider', 'permissions' => $frc_validation_sponsorship],\n                                  ['title' => '自动发布', 'anchor' => '#autorelease', 'permissions' => $frc_validation_sponsorship],\n                                  ['title' => '自动标签', 'anchor' => '#autotags', 'permissions' => $frc_validation_tags],\n                                  ['title' => '标签内链', 'anchor' => '#innerchain', 'permissions' => $frc_validation_chain],\n                                  ['title' => '动态内容', 'anchor' => '#dynamiccontent', 'permissions' => $frc_validation_dynamic],\n                                  ['title' => '数据发布控制', 'anchor' => '#release-control', 'permissions' => $frc_validation_release_control],\n                                  ['title' => '关键词随机插入', 'anchor' => '#insert-keyword', 'permissions' => $frc_validation_insert_keyword],\n//                        ['title' => '自动存图', 'anchor' => '#autosavepic', 'permissions' => $frc_validation_automatic_save_pic],\n                                  ['title' => '公众号历史文章采集', 'anchor' => '#wechat-history', 'permissions' => $frc_validation_wechat_history],\n\n                                  ['title' => '赞助鼠', 'anchor' => '#activation', 'permissions' => $frc_validation_sponsorship],\n                              ] as $i => $element) { ?>\n                    <button class=\"nav-link <?php $i == 0 ? _e('active') : ''; ?>\" data-bs-toggle=\"tab\" data-bs-target=\"<?php _e($element['anchor']); ?>\" type=\"button\">\n                        <?php _e($element['title']) ?>\n                        <?php if (!empty($element['permissions'])) {?>\n                            <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png'); ?>\" />\n                        <?php }?>\n                    </button>\n                <?php } ?>\n            </div>\n        </nav>\n\n        <p></p>\n        <div class=\"tab-content\">\n            <!--            首页-->\n            <div class=\"tab-pane fade show active\" id=\"kit\">\n                <p>欢迎来到胖鼠工具箱</p>\n                <h2 style=\"color: #4a148c\">胖鼠采集定时任务列表</h2>\n                <?php $crons = _get_cron_array();\n                $frc_cron_release_boolean = false;\n                $frc_cron_spider_boolean = false;\n                foreach ((array)$crons as $time => $cron){\n                    if (!is_array($cron)){\n                        continue;\n                    }\n                    foreach ($cron as $key => $value){\n                        if ($key == 'frc_cron_release_hook'){\n                            $frc_cron_release_boolean = true;\n                            _e(sprintf('<p><label class=\"label label-info\">胖鼠采集自动发布:下次执行时间 / %s</label></p>', date('Y-m-d h:i:s', strtotime(\"+8 hours\", $time))));\n                        }\n                        if ($key == 'frc_cron_spider_hook'){\n                            $frc_cron_spider_boolean = true;\n                            _e(sprintf('<p><label class=\"label label-info\">胖鼠采集自动采集:下次执行时间 / %s</label></p>', date('Y-m-d h:i:s', strtotime(\"+8 hours\", $time))));\n                        }\n                    }\n                }\n                if (!$frc_cron_release_boolean){\n                    _e('<p><label class=\"label label-warning\">胖鼠采集自动发布:未启动</label></p>');\n                }\n                if (!$frc_cron_spider_boolean){\n                    _e('<p><label class=\"label label-warning\">胖鼠采集自动采集:未启动</label></p>');\n                }\n                ?>\n                <hr />\n                <h6>鼠友你好, 如果您遇到定时任务不起作用, 是因为WP-Cron无法连续运行，这是一个wp问题。</h6>\n                <p>有一个简单的解决方案。只需将系统的任务计划程序设置为在所需的时间间隔（或在所需的特定时间）运行。最简单的解决方案是使用工具向wp-cron.php文件发出Web请求。</p>\n                <p>在系统上安排任务之后，还有一个步骤要完成。WordPress将在每次加载页面时继续运行WP-Cron。这不再是必需的，它将导致服务器上额外的资源使用。可以在wp-config.php文件中禁用WP-Cron</p>\n\n                <h6>1, 打开/wp-config.php文件进行编辑，并添加以下行:  </h6>\n                <h6><code>define('DISABLE_WP_CRON', true);</code></h6>\n                <h6>2, 添加系统定时任务 你要使用的命令是:</h6>\n                <h6><code>wget -qO- <?php esc_html_e(site_url( '/wp-cron.php' )); ?> &> /dev/null</code></h6>\n                2选1即可\n                <h6><code>curl <?php esc_html_e(site_url( '/wp-cron.php' )); ?>  &> /dev/null</code></h6>\n                <p><?php esc_html_e( '合理的时间间隔是 5-15 分钟. 这是 */5 * * * * 或 */15 * * * * 的时间间隔设置', 'Fat Rat Collect' ); ?>.</p>\n                <p>1, 第一步可优化节省服务器资源, 避免用户每次访问都查询cron, 优化服务速度 </p>\n                <p>2, 第二步是执行一个定时的请求, 每隔 5 - 15 分钟(推荐五分钟), 请求站点的/wp-cron.php文件</p>\n                <h6>linux OR ubuntu window 宝塔 都可以配置, 具体操作咨询服务商或百度</h6>\n                <h6>设置完成之后, 自动采集, 自动发布. 时间很准</h6>\n                <?php\n                if (isset($_REQUEST['all_collect'])){\n                    $frc_validation_all_collect = get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT);\n                    if ($frc_validation_all_collect === false) { ?>\n                        <h5>全站采集</h5>\n                        <input placeholder=\"请输入激活口令\" name=\"all-collect\"/>\n                        <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"all-collect\"\n                               value=\"激活\"/>\n                    <?php } else { ?>\n                        <h5>全站采集</h5>\n                        <img width=\"60\" src=\"<?php frc_image('fat-rat-success.png') ?>\">\n                        <label class=\"label label-success label-lg\">您于 <?php _e(@json_decode($frc_validation_all_collect)->created_at); ?> 已激活成功</label>\n                        <label class=\"label label-success label-lg\"></label>\n                        <p><label class=\"label label-info\">快去使用吧~</label></p>\n                        <?php\n                    }\n                }\n                if (isset($_REQUEST['rendering'])){\n                    $frc_validation_rendering = get_option(FRC_Validation::FRC_VALIDATION_RENDERING);\n                    if ($frc_validation_rendering === false) { ?>\n                        <h5>动态渲染</h5>\n                        <input placeholder=\"请输入激活口令\" name=\"rendering\"/>\n                        <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"rendering\"\n                               value=\"激活\"/>\n                    <?php } else { ?>\n                        <h5>全站采集</h5>\n                        <img width=\"60\" src=\"<?php frc_image('fat-rat-success.png') ?>\">\n                        <label class=\"label label-success label-lg\">您于 <?php _e(@json_decode($frc_validation_rendering)->created_at); ?> 已激活成功</label>\n                        <label class=\"label label-success label-lg\"></label>\n                        <p><label class=\"label label-info\">快去使用吧~</label></p>\n                        <?php\n                    }\n                }\n                ?>\n            </div>\n            <!--            自动爬虫-->\n            <div class=\"tab-pane fade\" id=\"autospider\">\n                <h5>自动采集</h5>\n                <ul>\n                    <?php $cron_spider = get_option('frc_cron_spider'); ?>\n                    <li><input type=\"radio\" name=\"frc_cron_spider\" value=\"\" <?php esc_attr_e(empty($cron_spider) ? 'checked' : ''); ?>> 关闭此功能</li>\n                    <?php foreach ($frc_wp_schedules as $key => $info){\n                        $disabled = '';\n                        if (empty($frc_validation_sponsorship) && $info['interval']<43200){\n                            $disabled = 'disabled';\n                        }\n                        _e(sprintf('<li><input type=\"radio\" name=\"frc_cron_spider\" value=\"%s\" %s %s> %s(%s秒)</li>', $key, (!empty($cron_spider) && $cron_spider == $key ? esc_html('checked') : ''), $disabled, $info['display'], $info['interval']));\n                    } ?>\n                </ul>\n                <p>胖鼠工具箱首页可看到爬虫目前的简单状态哦, 后续慢慢优化哦</p>\n                <p>或者下载安装插件 Advanced Cron Manager 里面 frc_ 开头的就是咱们的定时自动任务, 其他类似插件均可</p>\n                <input type=\"button\" class=\"frc_cron_button button button-primary\" data-value=\"frc_cron_spider\" value=\"设置\" />\n            </div>\n            <!--            自动发布-->\n            <div class=\"tab-pane fade\" id=\"autorelease\">\n                <h5>自动发布</h5>\n                <p>请鼠友给胖鼠<a href=\"https://wordpress.org/support/plugin/fat-rat-collect/reviews\" target=\"_blank\">五星评分</a>, 感谢!</p>\n                <ul>\n                    <?php $cron_release = get_option('frc_cron_release'); ?>\n                    <li><input type=\"radio\" name=\"frc_cron_release\" value=\"\" <?php esc_attr_e(empty($cron_release) ? 'checked' : ''); ?>> 关闭此功能</li>\n                    <?php foreach ($frc_wp_schedules as $key => $info){\n                        $disabled = '';\n                        if (empty($frc_validation_sponsorship) && $info['interval']<43200){\n                            $disabled = 'disabled';\n                        }\n                        _e(sprintf('<li><input type=\"radio\" name=\"frc_cron_release\" value=\"%s\" %s %s> %s(%s秒)</li>', $key, (!empty($cron_release) && $cron_release == $key ? esc_html('checked') : ''), $disabled, $info['display'], $info['interval']));\n                    } ?>\n                </ul>\n                <input type=\"button\" class=\"frc_cron_button button button-primary\" data-value=\"frc_cron_release\" value=\"设置\" />\n            </div>\n            <!--            自动标签-->\n            <div class=\"tab-pane fade\" id=\"autotags\">\n                <h5>自动标签</h5>\n                <?php\n                if ($frc_validation_tags != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_tags)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <p><a href=\"https://www.fatrat.cn/docs/v2/auto-tags\" target=\"_blank\">Auto Tags</a> （文章自动打标签）</p>\n                <p>此功能不依赖胖鼠采集, 属可独立运行功能！</p>\n                <p>自动标签意指为文章自动打标签！</p>\n                <p>第一步把你的标签输入进标签库！</p>\n                <p>新发布的文章会在发布的同时, 会自动匹配标签库标签.</p>\n                <p>关键词命中就会自动打标签, 升级后英文不区分大小写.</p>\n                <p>省时省力还省心！</p>\n                <?php\n                if ($frc_validation_tags === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"auto-tags\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"auto-tags\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <?php\n                    $conf_json = json_decode($frc_validation_tags);\n                    $switch_text = $conf_json->switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态';\n                    $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动';\n                    _e(sprintf('<h3><p class=\"label label-info\">%s</p></h3>', $switch_text));\n                    _e(sprintf('<p><input type=\"button\" class=\"frc-function-switch button button-primary\" data-value=\"auto-tags\" value=\"%s\" /></p>', $subsequent_text));\n                } ?>\n            </div>\n            <!--            标签内链-->\n            <div class=\"tab-pane fade\" id=\"innerchain\">\n                <p><h5>标签内链</h5></p>\n                <?php\n                if ($frc_validation_chain != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_chain)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <p>开启后会给文章中的标签增加标签列表页的链接</p>\n                <p>每个标签目前只增加一次链接</p>\n                <p>配合自动标签更完美, 省时省力还省心.</p>\n                <?php\n                if ($frc_validation_chain === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"inner-chain\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"inner-chain\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <?php\n                    $conf_json = json_decode($frc_validation_chain);\n                    $switch_text = $conf_json->switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态';\n                    $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动';\n                    _e(sprintf('<h3><p class=\"label label-info\">%s</p></h3>', $switch_text));\n                    _e(sprintf('<input type=\"button\" class=\"frc-function-switch button button-primary\" data-value=\"inner-chain\" value=\"%s\" />', $subsequent_text));\n                } ?>\n            </div>\n            <!--            动态内容-->\n            <div class=\"tab-pane fade\" id=\"dynamiccontent\">\n                <p><h5>动态内容</h5></p>\n                <?php\n                if ($frc_validation_dynamic != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_dynamic)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <p><a href=\"https://www.fatrat.cn/docs/v2/dynamic-content\" target=\"_blank\">Dynamic Content</a> （文章自动添加动态内容）</p>\n                <p>动态内容不依赖胖鼠采集, 属可独立运行功能！</p>\n                <p>动态内容是为文章自动添加一段动态内容！</p>\n                <p>指在文章正文开头、结尾各插入一段其他文章内容 (新版本去掉开头的内容)</p>\n                <p>插入的内容来自: 同分类下,最近七天的随机文章，如果没有找到七天内文章, 就不添加</p>\n                <p>文章正文前后插入内容后, 有利于收录, 并且不影响用户阅读.</p>\n                <p>动态内容胖鼠推荐使用!!! 省时省力还省心!</p>\n                <?php\n                if ($frc_validation_dynamic === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"dynamic-fields\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"dynamic-fields\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <p class=\"label label-success\">您已激活成功</p>\n                    <?php\n                    $conf_json = json_decode($frc_validation_dynamic);\n                    $switch_text = $conf_json->switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态';\n                    $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动';\n                    _e(sprintf('<h3><p class=\"label label-info\">%s</p></h3>', $switch_text));\n                    _e(sprintf('<input type=\"button\" class=\"frc-function-switch button button-primary\" data-value=\"dynamic-fields\" value=\"%s\" />', $subsequent_text));\n                } ?>\n            </div>\n            <!--            数据发布控制-->\n            <div class=\"tab-pane fade\" id=\"release-control\">\n                <p><h5>数据发布控制</h5></p>\n                <?php\n                if ($frc_validation_release_control != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_release_control)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <p>此功能激活后: 可操作发布页面所有选项。</p>\n                <?php\n                if ($frc_validation_release_control === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"release-control\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"release-control\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <p class=\"label label-success\">您已激活成功</p>\n                <?php } ?>\n            </div>\n            <!--            关键词随机插入-->\n            <div class=\"tab-pane fade\" id=\"insert-keyword\">\n                <p><h5>关键词随机插入</h5></p>\n                <?php\n                if ($frc_validation_insert_keyword != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_insert_keyword)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <?php\n                if ($frc_validation_insert_keyword === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"insert-keyword\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"insert-keyword\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <?php\n                    $conf_json = json_decode($frc_validation_insert_keyword);\n                    $switch_text = $conf_json->switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态';\n                    $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动';\n                    _e(sprintf('<h3><p class=\"label label-info\">%s</p></h3>', $switch_text));\n                    _e(sprintf('<input type=\"button\" class=\"frc-function-switch button button-primary\" data-value=\"insert-keyword\" value=\"%s\" />', $subsequent_text));\n                } ?>\n            </div>\n            <!--            自动保存图片-->\n            <div class=\"tab-pane fade\" id=\"autosavepic\">\n                <p><h5>从其他站点手动复制过来的文章，点击保存后，所有远程图片自动本地化</h5></p>\n                <p><h5>待开发</h5></p>\n                <?php\n                if ($frc_validation_automatic_save_pic != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_automatic_save_pic)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <p>开启后会给文章中的标签增加标签列表页的链接</p>\n                <p>每个标签目前只增加一次链接</p>\n                <p>配合自动标签更完美, 省时省力还省心.</p>\n                <?php\n                if ($frc_validation_automatic_save_pic === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"automatic-save-pic\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"automatic-save-pic\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <?php\n                    $conf_json = json_decode($frc_validation_automatic_save_pic);\n                    $switch_text = $conf_json->switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态';\n                    $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动';\n                    _e(sprintf('<h3><p class=\"label label-info\">%s</p></h3>', $switch_text));\n                    _e(sprintf('<input type=\"button\" class=\"frc-function-switch button button-primary\" data-value=\"automatic-save-pic\" value=\"%s\" />', $subsequent_text));\n                } ?>\n            </div>\n            <!--            赞助鼠-->\n            <div class=\"tab-pane fade\" id=\"activation\">\n                <?php\n                if (get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP) === false) { ?>\n                    <h5>赞助鼠</h5>\n                    <p><a href=\"https://www.fatrat.cn/docs/v2/sponsorship\" target=\"_blank\">https://www.fatrat.cn/docs/v2/sponsorship</a></p>\n                    <input placeholder=\"请输入激活口令\" name=\"sponsorship\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"sponsorship\"\n                           value=\"赞助激活\"/>\n                <?php } else { ?>\n                    <h2 style=\"color: #00b300\">感谢赞助支持. 您享有胖鼠采集所有功能</h2>\n                <?php } ?>\n\n\n            </div>\n\n            <!--            公众号历史文章采集-->\n            <div class=\"tab-pane fade\" id=\"wechat-history\">\n                <p><h5>公众号历史文章采集</h5></p>\n                <?php\n                if ($frc_validation_wechat_history != false){\n                    _e('<p><label class=\"label label-success label-lg\">您于 '.@json_decode($frc_validation_wechat_history)->created_at.' 已激活成功</label></p>');\n                }\n                ?>\n                <?php\n                if ($frc_validation_wechat_history === false) { ?>\n                    <input placeholder=\"请输入激活口令\" name=\"wechat-history\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"wechat-history\"\n                           value=\"激活\"/>\n                <?php } else { ?>\n                    <h2 style=\"color: #00b300\">感谢支持</h2>鼠友限时享有胖鼠采集公众号历史文章采集功能</h2>\n                    <input hidden=\"hidden\" placeholder=\"请输入激活口令\" name=\"wechat-history\"/>\n                    <input type=\"button\" class=\"frc-activation button button-primary\" data-value=\"wechat-history\"\n                           value=\"更新激活\"/>\n                <?php } ?>\n            </div>\n        </div>\n    </div>\n    <?php\n}"
  },
  {
    "path": "includes/fatrat-options-add-edit.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2018年12月30日 02:24\n */\n\n\nfunction frc_options_add_edit()\n{\n    $option = null;\n    $custom_content = null;\n    $rule_link = $rule_title = $rule_content = $rule_paging = [];\n    $option_id = frc_sanitize_text('option_id', 0);\n    if ($option_id) {\n        $options = new FRC_Options();\n        $option = $options->option($option_id);\n\n\t    // 全站采集转义数据处理\n        if ($option['collect_type'] == 'all'){\n\t        $option['collect_list_range'] = str_replace(\"\\\\\\\\\", \"\\\\\", htmlspecialchars_decode($option['collect_list_range']));\n        }\n\n\t    // 转义数据处理\n        $option['collect_keywords_replace_rule'] = str_replace(\" \", \"\\n\", $option['collect_keywords_replace_rule']);\n        $custom_content = json_decode(!empty($option['collect_custom_content'])?$option['collect_custom_content']:'{\"head\":\"\",\"foot\":\"\"}', true);\n        $custom_content['head'] = str_replace('\\\\\"', '\"', htmlspecialchars_decode($custom_content['head']));\n        $custom_content['foot'] = str_replace('\\\\\"', '\"', htmlspecialchars_decode($custom_content['foot']));\n\n        // TODO: optimized\n        $list_rules = translationRules($option['collect_list_rules']);\n        $rule_link = [\n            'a' => 'link',\n            'b' => $list_rules['link']['selector']??'',\n            'c' => $list_rules['link']['attribute']??'',\n            'd' => $list_rules['link']['filter']??'',\n        ];\n        foreach (translationRules($option['collect_content_rules']) as $key => $val){\n            $value = [\n                'a' => $key,\n                'b' => $val['selector'],\n                'c' => $val['attribute'],\n                'd' => $val['filter'],\n            ];\n\n            if ($key == 'title'){\n                $rule_title = $value;\n            } elseif ($key == 'content'){\n                $rule_content = $value;\n            } elseif ($key == 'paging'){\n                $rule_paging = $value;\n            }\n        }\n    }\n\n    $frc_validation_sponsorship = get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP);\n    $frc_validation_all_collect = get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT);\n\n    ?>\n\n    <div class=\"wrap frc-option-add-edit\">\n        <h1>\n            <?php _e((isset($option)) ? '修改' : '新建' ) ?>配置规则\n            <?php if (!empty($frc_validation_sponsorship)) { ?>\n                <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png') ?>\" />\n            <?php } ?>\n        </h1>\n        <p style=\"color: #838382\">欢迎你使用胖鼠创建自己的规则, 如果第一次遇见认识胖鼠. 点<a href=\"https://www.fatrat.cn/docs/v2/create-rules\" target=\"_blank\">这里</a></p>\n        <input type=\"hidden\" hidden id=\"success_redirect_url\"\n               value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-options')); ?>\">\n        <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n        <input type=\"hidden\" hidden id=\"option_id\" value=\"<?php frc_option_esc_attr_e($option, 'id'); ?>\">\n\t    <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n        <table class=\"form-table\">\n            <tr>\n                <th>配置名称:</th>\n                <td><input type=\"text\" size=\"50\" name=\"collect_name\"\n                        <?php if (isset($option['collect_name']) && in_array($option['collect_name'], FRC_ApiError::BUTTON_DISABLED)){ esc_attr_e('disabled'); } ?>\n                           value=\"<?php frc_option_esc_attr_e($option, 'collect_name'); ?>\" placeholder=\"我的第一个胖鼠采集规则\"/>*\n                </td>\n            </tr>\n            <tr>\n                <th>一句话的描述:</th>\n                <td><input type=\"text\" size=\"50\" name=\"collect_describe\"\n                           value=\"<?php frc_option_esc_attr_e($option, 'collect_describe'); ?>\" placeholder=\"胖鼠采集, WordPress 最好用的文章采集器\"/>\n                </td>\n            </tr>\n            <tr>\n                <th>配置类型:</th>\n                <td>\n                    <input type=\"radio\" name=\"collect_type\" checked\n                            <?php if (isset($option['collect_name']) && in_array($option['collect_name'], FRC_ApiError::BUTTON_DISABLED)){ esc_attr_e('disabled'); } ?>\n                           value=\"list\" <?php esc_attr_e(isset($option) ? ($option['collect_type'] == 'list' ? 'checked' : '') : ''); ?> >\n                    列表采集配置\n                    <input type=\"radio\" name=\"collect_type\"\n                           value=\"single\" <?php esc_attr_e( isset($option) ? ($option['collect_type'] == 'single' ? 'checked' : '') : ''); ?> >\n                    详情采集配置\n                    <?php if ($frc_validation_all_collect){ ?>\n                    <input type=\"radio\" name=\"collect_type\"\n                           value=\"all\" <?php esc_attr_e( isset($option) ? ($option['collect_type'] == 'all' ? 'checked' : '') : ''); ?> >\n                    全站采集\n                    <p>全站采集: 采集范围处写全站正则, <a href=\"https://www.fatrat.cn/docs/v2/total-station-collect\" target=\"_blank\">参考</a></p>\n                    <p>全站采集: 采集规则处不填</p>\n                    <?php }?>\n                    <p>列表可直接写采集地址. 详情只写规则, 采集地址在使用的时候填写即可.</p>\n                </td>\n            </tr>\n            <?php if (get_option(FRC_Validation::FRC_VALIDATION_RENDERING)) { ?>\n            <tr>\n                <th>采集方式:</th>\n                <td>\n                    <input type=\"radio\" name=\"collect_rendering\" checked\n                           value=\"1\" <?php esc_attr_e( isset($option) ? ($option['collect_rendering'] == '1' ? 'checked' : '') : ''); ?> >\n                    静态渲染\n                    <input type=\"radio\" name=\"collect_rendering\"\n                           value=\"2\" <?php esc_attr_e( isset($option) ? ($option['collect_rendering'] == '2' ? 'checked' : '') : ''); ?> >\n                    动态渲染\n                    <p>静态渲染: 普通页面, 动态渲染: ajax页面</p>\n                </td>\n            </tr>\n            <?php } ?>\n            <tr>\n                <th>编码处理:</th>\n                <td>\n                    <input type=\"radio\" name=\"collect_remove_head\" checked\n                           value=\"1\" <?php esc_attr_e( isset($option) ? ($option['collect_remove_head'] == '1' ? 'checked' : '') : ''); ?> >\n                    自动识别(推荐)\n                    <input type=\"radio\" name=\"collect_remove_head\"\n                           value=\"2\" <?php esc_attr_e( isset($option) ? ($option['collect_remove_head'] == '2' ? 'checked' : '') : ''); ?> >\n                    删HEAD(非UTF-8编码推荐)\n                    <input type=\"radio\" name=\"collect_remove_head\"\n                           value=\"3\" <?php esc_attr_e( isset($option) ? ($option['collect_remove_head'] == '3' ? 'checked' : '') : ''); ?> <?php if (!$frc_validation_sponsorship) { esc_attr_e( 'disabled' ); }?> >\n                    <span style=\"color: #db9925\">强制转换(终极方案)</span>\n\n                    <p>此功能用于解决乱码问题,自动识别转码失败你可尝试删HEAD,强制转换,选的不对有可能会取不到数据哦.</p>\n                </td>\n            </tr>\n            <tr>\n                <th>图片下载:</th>\n                <td>\n                    <input type=\"radio\"  name=\"collect_image_download\" value=\"1\" <?php esc_attr_e( isset($option) ? ($option['collect_image_download'] == '1' ? 'checked' : '') : 'checked' );?> >\n                    下载到本地(推荐)\n                    <input type=\"radio\"  name=\"collect_image_download\" value=\"2\" <?php esc_attr_e( isset($option) ? ($option['collect_image_download'] == '2' ? 'checked' : '') : '' );?> >\n                    不下载\n                    <input type=\"radio\"  name=\"collect_image_download\" value=\"3\" <?php esc_attr_e( isset($option) ? ($option['collect_image_download'] == '3' ? 'checked' : '') : '' );?> >\n                    删除图片\n                    <input type=\"radio\"  name=\"collect_image_download\" value=\"4\" <?php esc_attr_e( isset($option) ? ($option['collect_image_download'] == '4' ? 'checked' : '') : '' );?> <?php if (!$frc_validation_sponsorship) { esc_attr_e( 'disabled' ); }?> >\n                    <span style=\"color: #db9925\">图片下载不入媒体库</span>\n                    <p>「经典速度」  下载到本地: 可安装云存储插件对接云存储</p>\n                    <p>「高速采集」  不下载:     使用源站图片路径, 如果源站图片路径是相对路径, 会把地址补全</p>\n                    <p>「超超高速采集」删除图片:   删除正文所有<\\img > </p>\n                    <p>「经典速度」  图片下载不入媒体库: 图片已经下载, 但是不上传到媒体库中「发布文章速度: 超快」 </p>\n                </td>\n            </tr>\n            <tr>\n                <th>图片路径:</th>\n                <td>\n                    <input type=\"radio\"  name=\"collect_image_path\" value=\"1\" <?php esc_attr_e( isset($option) ? ($option['collect_image_path'] == '1' ? 'checked' : '') : 'checked' ); ?> >\n                    绝对路径(OSS/云存储必选)\n                    <input type=\"radio\"  name=\"collect_image_path\" value=\"2\" <?php esc_attr_e( isset($option) ? ($option['collect_image_path'] == '2' ? 'checked' : '') : '' ); ?> >\n                    相对路径(本地存储图片)\n                    <p>绝对路径格式: https://www.xxx.com/wp-content/uploads/2020/05/A.jpg</p>\n                    <p>相对路径格式: /wp-content/uploads/2020/05/A.jpg</p>\n                </td>\n            </tr>\n<!--            <tr>-->\n<!--                <th>去除标签中Css样式/注释:</th>-->\n<!--                <td>-->\n<!--                    <input type=\"text\" size=\"82\"-->\n<!--                           value=\"--><?php //esc_attr_e( isset($option) ? $option['collect_list_url'] : ''); ?><!--\"-->\n<!--                           name=\"collect_list_url\"  />*-->\n<!--                </td>-->\n<!--            </tr>-->\n            <tr class=\"collect_type_radio_change\">\n                <th>采集地址:</th>\n                <td><input type=\"text\" size=\"82\"\n                           value=\"<?php frc_option_esc_attr_e($option, 'collect_list_url'); ?>\"\n                           name=\"collect_list_url\"  />*\n                    <p>小提示: 不清楚下面的规则怎么写? 去试试debug功能吧 ~ </p>\n                </td>\n            </tr>\n            <tr class=\"collect_type_radio_change\">\n                <th>分页采集地址:</th>\n                <td><input type=\"text\" size=\"82\"\n                           value=\"<?php frc_option_esc_attr_e($option, 'collect_list_url_paging'); ?>\"\n                           name=\"collect_list_url_paging\"  />\n                    <p>把页码的码数替换为 {page} 注: 非列表采集不填</p>\n                    <p>例子: https://xx.qq.com/webplat/info/news_version3/154/2233/3889/m2702/list_{page}.shtml</p>\n                </td>\n            </tr>\n            <tr class=\"collect_type_radio_change\">\n                <th>采集范围:</th>\n                <td><input type=\"text\" size=\"82\"\n                           value=\"<?php frc_option_esc_attr_e($option, 'collect_list_range'); ?>\"\n                           name=\"collect_list_range\" />*\n                    <p>填写Html标签的 class 或者 id (Jquery语法) 采集范围<a href=\"https://www.fatrat.cn/docs/v2/core-rules\" target=\"_blank\">参考</a></p>\n                </td>\n            </tr>\n            <tr class=\"collect_type_radio_change\">\n                <th>采集规则:</th>\n                <td>\n                    &nbsp;&nbsp;&nbsp;<span style=\"color: #CC6633\">规则名&nbsp;&nbsp;- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JQuery选择器 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n                    &nbsp;&nbsp;&nbsp;- &nbsp;属性 &nbsp; - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;内容过滤: 空格分割</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a\n                            href=\"http://jquery.cuishifeng.cn/\" target='_blank'>Jquery手册</a><br/>\n                    <input type=\"text\" size=\"6\" value=\"<?php esc_attr_e( isset($option) ? $rule_link['a'] : 'link' ); ?>\"\n                           disabled name=\"collect_list_rule_link_a\"/>-<input type=\"text\" size=\"20\"\n                                                                             value=\"<?php esc_attr_e( isset($option) ? $rule_link['b'] : ''); ?>\"\n                                                                             name=\"collect_list_rule_link_b\"/>-<input\n                            type=\"text\" size=\"4\" value=\"<?php esc_attr_e( isset($option) ? $rule_link['c'] : ''); ?>\"\n                            name=\"collect_list_rule_link_c\"/>-<input type=\"text\" size=\"40\"\n                                                                     value=\"<?php esc_attr_e( isset($option) ? $rule_link['d'] : ''); ?>\"\n                                                                     name=\"collect_list_rule_link_d\"/>*\n                    <p>列表页 我们只取详情页的url链接即可</p>\n                </td>\n            </tr>\n            <tr>\n                <th>详情页面采集区域:</th>\n                <td><input type=\"text\" size=\"82\"\n                           value=\"<?php frc_option_esc_attr_e($option, 'collect_content_range'); ?>\"\n                           name=\"collect_content_range\"/>*\n                    <p>填写Html标签的 class 或者 id (Jquery语法) <a href=\"https://www.fatrat.cn/docs/v2/core-rules\" target=\"_blank\">参考</a></p>\n                </td>\n            </tr>\n            <tr>\n                <th>详情页面采集规则:</th>\n                <td>\n                    &nbsp;&nbsp;&nbsp;<span style=\"color: #CC6633\">规则名&nbsp;&nbsp;- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JQuery选择器 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n                    &nbsp;&nbsp;&nbsp;- &nbsp;属性 &nbsp; - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;内容过滤: 空格分割</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a\n                            href=\"http://jquery.cuishifeng.cn/\" target='_blank'>Jquery手册</a><br/>\n                    <input type=\"text\" size=\"6\"\n                           value=\"<?php esc_attr_e( isset($rule_title['a']) ? $rule_title['a'] : 'title'); ?>\" disabled\n                           name=\"collect_content_rule_title_a\"/>-<input type=\"text\" size=\"20\"\n                                                                        value=\"<?php esc_attr_e( isset($rule_title['b']) ? $rule_title['b'] : ''); ?>\"\n                                                                        name=\"collect_content_rule_title_b\"/>-<input\n                            type=\"text\" size=\"4\" value=\"<?php esc_attr_e( isset($rule_title['c']) ? $rule_title['c'] : ''); ?>\"\n                            name=\"collect_content_rule_title_c\"/>-<input type=\"text\" size=\"40\"\n                                                                         value=\"<?php esc_attr_e( isset($rule_title['d']) ? $rule_title['d'] : ''); ?>\"\n                                                                         name=\"collect_content_rule_title_d\"/>*\n                    <br/>\n                    <input type=\"text\" size=\"6\"\n                           value=\"<?php esc_attr_e( isset($rule_content['a']) ? $rule_content['a'] : 'content'); ?>\" disabled\n                           name=\"collect_content_rule_content_a\"/>-<input type=\"text\" size=\"20\"\n                                                                          value=\"<?php esc_attr_e( isset($rule_content['b']) ? $rule_content['b'] : ''); ?>\"\n                                                                          name=\"collect_content_rule_content_b\"/>-<input\n                            type=\"text\" size=\"4\"\n                            value=\"<?php esc_attr_e( isset($rule_content['c']) ? $rule_content['c'] : ''); ?>\"\n                            name=\"collect_content_rule_content_c\"/>-<input type=\"text\" size=\"40\"\n                                                                           value=\"<?php esc_attr_e( isset($rule_content['d']) ? $rule_content['d'] : ''); ?>\"\n                                                                           name=\"collect_content_rule_content_d\"/>*\n                    <br/>\n                    <input type=\"text\" size=\"6\"\n                           value=\"<?php esc_attr_e( isset($rule_paging['a']) ? $rule_paging['a'] : 'paging'); ?>\" disabled\n                           name=\"collect_content_rule_paging_a\"/>-<input type=\"text\" size=\"20\" placeholder=\"a:contains(下一页)\"\n                                                                          value=\"<?php esc_attr_e( isset($rule_paging['b']) ? $rule_paging['b'] : ''); ?>\"\n                                                                          name=\"collect_content_rule_paging_b\"/>-<input\n                            type=\"text\" size=\"4\"\n                            value=\"<?php esc_attr_e( isset($rule_paging['c']) ? $rule_paging['c'] : ''); ?>\"\n                            name=\"collect_content_rule_paging_c\"/>-<input type=\"text\" size=\"40\"\n                                                                           value=\"<?php esc_attr_e( isset($rule_paging['d']) ? $rule_paging['d'] : ''); ?>\"\n                                                                           name=\"collect_content_rule_paging_d\"/>\n                    <p>详情页,我们只拿 Title Content 一片文章岂不是就有了. 其他字段如 日期/作者 回头考虑怎么开放给大家用.. </p>\n                    <p>Paging字段为详情页内容分页采集功能, 细节用法参考官网文档</p>\n                </td>\n            </tr>\n            <tr>\n                <th>cookie:</th>\n                <td>\n                    <textarea name=\"collect_cookie\" cols=\"80\" rows=\"3\" placeholder=\"\"><?php if (!empty($option)){ esc_html_e($option['collect_cookie'], ''); } ?></textarea>\n                    <p>不需要登陆就可采集的不用填写,cookie可能需要根据不同网站不同需要定时更新。</p>\n                </td>\n            </tr>\n            <tr>\n                <th>图片源属性:</th>\n                <td>\n                    <input type=\"text\" size=\"82\"\n                           value=\"<?php esc_attr_e( isset($option) ? $option['collect_image_attribute'] : 'src'); ?>\"\n                           name=\"collect_image_attribute\"/>\n                    <p>默认即可。某些站点图片是使用 Js 异步加载。此选项用来设置真实图片地址的属性。</p>\n                </td>\n            </tr>\n            <tr>\n                <th>内容插入:</th>\n                <td>\n                    <p style=\"color: #CC6633\">插入文章开头</p>\n                    <textarea name=\"collect_custom_content_head\" cols=\"80\" rows=\"3\" placeholder=\"\"><?php if (!empty($custom_content)){ esc_html_e($custom_content['head'], 'Far Rat Collect'); } ?></textarea>\n                    <br />\n                    <p style=\"color: #CC6633\">插入文章结尾</p>\n                    <textarea name=\"collect_custom_content_foot\" cols=\"80\" rows=\"3\" placeholder=\"\"><?php if (!empty($custom_content)){ esc_html_e($custom_content['foot'], 'Far Rat Collect'); } else { esc_html_e('文章来源于互联网:{title+link}', 'Far Rat Collect'); } ?></textarea>\n                    <p>可使用的变量: {title} | {link} | {title+link} <a href=\"https://www.fatrat.cn/docs/v2/variable-expansion\" target=\"_blank\">参考</a></p>\n                </td>\n            </tr>\n            <tr>\n                <th scope=\"row\">关键词替换</th>\n                <td>\n                    <textarea name=\"collect_keywords_replace_rule\" cols=\"80\" rows=\"8\" placeholder=\"在此输入关键词替换规则,可以替换替换标题和内容的数据\n例:\n苹果=橘子\n小蝌蚪=蝌蚪宝宝\n妻子=老婆\"><?php esc_html_e( isset($option) ? $option['collect_keywords_replace_rule'] : ''); ?></textarea><p>注: 阿拉伯数字1 2 3 和 英文字符 a b c 不可以配置替换. 可能会把内容图片URL替换成错误的. 别乱搞哦</p>\n                </td>\n            </tr>\n            <tr>\n                <th scope=\"row\">关键词随机插入</th>\n                <td>\n                    <textarea name=\"collect_keywords\" cols=\"80\" rows=\"8\" placeholder=\"[\n    {'count':'2', 'title':'胖鼠采集', 'link':'https://www.fatrat.cn'}\n]\"><?php esc_html_e( isset($option) ? $option['collect_keywords'] : ''); ?></textarea>\n                    <p><a href=\"javascript:\" id=\"keywords_default\">默认数据</a> | <a href=\"http://json.cn/\" target=\"_blank\">Json格式效验</a></p>\n                </td>\n            </tr>\n            <tr>\n                <th colspan=\"2\"><input class=\"button button-primary\" type=\"button\" id=\"save-option-button\" value=\"保存\"/>\n                    <p></p><p>带*号必填且不可错误的</p>\n                </th>\n            </tr>\n        </table>\n    </div>\n    <?php\n}"
  },
  {
    "path": "includes/fatrat-options.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2018年12月30日 02:24\n */\n\nif (!class_exists('WP_List_Table')) {\n    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');\n}\n\nclass FRC_Options\n{\n    protected $wpdb;\n    protected $table_options;\n\n\n    public function __construct()\n    {\n        global $wpdb;\n        $this->wpdb = $wpdb;\n        $this->table_options = $wpdb->prefix . 'frc_options';\n    }\n\n\n    /**\n     * @param int $page_number\n     * @param int $per_page\n     * @param string $customvar\n     *\n     * @return array\n     */\n    public function options_paging(int $page_number = 1, int $per_page = 10, string $customvar = 'total'): array\n    {\n        $sql = \"SELECT * FROM $this->table_options\";\n\n        if (in_array($customvar, array('list', 'single', 'all'))) {\n            $sql = $this->wpdb->prepare(\"$sql where `collect_type` = '%s'\", $customvar);\n        }\n\n        if (!empty($_REQUEST['orderby'])) {\n            $by = frc_sanitize_text('orderby');\n            $sort = !empty($_REQUEST['order']) ? frc_sanitize_text('order') : 'ASC';\n            $sql = $this->wpdb->prepare(\"$sql ORDER BY $by $sort\");\n        } else {\n            $sql .= ' ORDER BY id DESC';\n        }\n\n        $sql = $this->wpdb->prepare(\"$sql LIMIT %d OFFSET %d\", (int) $per_page, (int) (($page_number - 1) * $per_page));\n\n        return $this->wpdb->get_results($sql, 'ARRAY_A');\n    }\n\n\n    /**\n     * @return array|null|object\n     */\n    public function options(){\n        return $this->wpdb->get_results($this->wpdb->prepare(\"select * from %i \",$this->table_options),ARRAY_A);\n    }\n\n\n    /**\n     * @param int $option_id\n     * @return array|null|object|void\n     */\n    public function option(int $option_id): array\n    {\n        return $this->wpdb->get_row($this->wpdb->prepare(\"select * from $this->table_options where `id` = %d\", $option_id),ARRAY_A);\n    }\n\n\n    /**\n     * @param $id\n     * @return false|int\n     */\n    public function delete($id)\n    {\n        $re = $this->wpdb->delete(\n            $this->table_options, array('id' => $id), array('%d')\n        );\n        (new FRC_Data())->delete_by_option($id);\n        return $re;\n    }\n\n\n    /**\n     * @param $name\n     * @return array|null|object|void\n     */\n    public function lazy_person($name){\n        $option = $this->option_by_key($name, 'collect_name');\n        if (empty($option)){\n            // 默认生成基础配置\n            $this->insert_option($name);\n            $option = $this->option_by_key($name, 'collect_name');\n        }\n\n        return $option;\n    }\n\n    /**\n     * @param $name\n     * @param $key\n     * @return array|null|object|void\n     */\n    public function option_by_key($name, $key)\n    {\n        return  $this->wpdb->get_row($this->wpdb->prepare(\"SELECT * FROM {$this->table_options} WHERE `{$key}` = '%s'\", $name), ARRAY_A );\n    }\n\n\n    /**\n     * @param string $customvar\n     * @return null|string\n     */\n    public function record_count(string $customvar = 'total')\n    {\n        $sql = \"SELECT COUNT(*) FROM $this->table_options\";\n        if (in_array($customvar, array('list', 'single', 'all', 'keyword'))) {\n            $sql = $this->wpdb->prepare(\"$sql where collect_type = %s\", $customvar);\n        }\n\n        return $this->wpdb->get_var($sql);\n    }\n\n\n\n    /**\n     * @param $name\n     * @return array|null|object|void\n     */\n    public function insert_option($name)\n    {\n        $date = current_time('mysql');\n        if ($name == '微信'){\n            $sql = \"INSERT INTO `{$this->table_options}` SET `collect_name` = '微信', `collect_describe` = '胖鼠采集. WordPress 最好用的采集小插件. ', `collect_type` = 'single', `collect_image_attribute` = 'data-src', `collect_content_range` = '#img-content',  `collect_content_rules` = 'title%#activity-name|text|null)(content%#js_content|html|null)(author%#js_author_name|text|null)(name%#js_name|text|null', `created_at` = '{$date}', `updated_at` = '{$date}'\";\n        } elseif ($name == '简书'){\n            $sql = \"INSERT INTO `{$this->table_options}` SET `collect_name` = '简书', `collect_describe` = '胖鼠采集. WordPress 最好用的采集小插件. ', `collect_type` = 'single', `collect_image_attribute` = 'data-original-src', `collect_content_range` = 'body',  `collect_content_rules` = 'title%h1:first|text|null)(content%article|html|a', `created_at` = '{$date}', `updated_at` = '{$date}'\";\n        }  elseif ($name == '知乎'){\n            $sql = \"INSERT INTO `{$this->table_options}` SET `collect_name` = '知乎', `collect_describe` = '胖鼠采集. WordPress 最好用的采集小插件. ', `collect_type` = 'single', `collect_image_attribute` = 'data-actualsrc', `collect_content_range` = '.App-main',  `collect_content_rules` = 'title%.QuestionHeader-title|text|null)(content%.RichContent-inner|html|a -.LinkCard-content', `created_at` = '{$date}', `updated_at` = '{$date}'\";\n        } else {\n            return ;\n        }\n\n        return $this->wpdb->query($sql);\n    }\n\n\n    /**\n     * @return array\n     */\n    public function interface_save_option(){\n\n        if (!get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP)){\n            if (count($this->options()) > 5){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => FRC_Validation::FRC_HINT_Z];\n            }\n        }\n\n        $option_id                  = frc_sanitize_text('option_id', null);\n        $collect_name               = frc_sanitize_text('collect_name');\n        $collect_describe           = frc_sanitize_text('collect_describe', '胖鼠采集, Wordpress最好用的采集神器.');\n        $collect_type               = frc_sanitize_text('collect_type', 'list');\n        $collect_cookie             = frc_sanitize_text('collect_cookie', '');\n        $collect_rendering          = (int) frc_sanitize_text('collect_rendering', 1);\n        $collect_image_download     = (int) frc_sanitize_text('collect_image_download', 1);\n        $collect_image_path         = (int) frc_sanitize_text('collect_image_path', 1);\n        $collect_remove_head        = (int) frc_sanitize_text('collect_remove_head', 1);\n        $collect_list_url           = frc_sanitize_text('collect_list_url');\n        $collect_list_url_paging    = frc_sanitize_text('collect_list_url_paging');\n        $collect_list_range         = frc_sanitize_text('collect_list_range');\n        $collect_list_rules         = frc_sanitize_text('collect_list_rules');\n        $collect_content_range      = frc_sanitize_text('collect_content_range');\n        $collect_content_rules      = frc_sanitize_text('collect_content_rules');\n        $collect_image_attribute    = frc_sanitize_text('collect_image_attribute', 'src');\n        $collect_custom_content_head = frc_sanitize_textarea('collect_custom_content_head');\n        $collect_custom_content_foot = frc_sanitize_textarea('collect_custom_content_foot');\n        $collect_keywords_replace_rule = frc_sanitize_text('collect_keywords_replace_rule');\n        $collect_keywords = frc_sanitize_textarea('collect_keywords', '');\n\n        if ($collect_name == ''){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '给你的配置写个名字吧, 着啥急'];\n        }\n        if ($collect_type == 'list'){\n            if ($collect_list_url == ''){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => '请填写采集地址.'];\n            }\n            if (empty($collect_list_range) || empty($collect_list_rules)){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => '列表采集范围/采集规则为空.'];\n            }\n        }\n        if (empty($collect_content_range) || empty($collect_content_rules)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '详情采集范围/采集规则为空.'];\n        }\n\n        if ($collect_keywords != ''){\n            $collect_keywords = str_replace('\\\"', '\"', htmlspecialchars_decode($collect_keywords, ENT_QUOTES));\n            if (!json_decode($collect_keywords)){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => '关键词随机插入Json错误'];\n            }\n        }\n\n        $params = [\n            'collect_name' => $collect_name,\n            'collect_describe' => $collect_describe,\n            'collect_type' => $collect_type,\n            'collect_cookie'=>$collect_cookie,\n            'collect_rendering' => $collect_rendering,\n            'collect_image_download' => $collect_image_download,\n            'collect_image_path' => $collect_image_path,\n            'collect_remove_head' => $collect_remove_head,\n            'collect_list_url' => $collect_list_url,\n            'collect_list_url_paging' => $collect_list_url_paging,\n            'collect_list_range' => $collect_list_range,\n            'collect_list_rules' => $collect_list_rules,\n            'collect_content_range' => $collect_content_range,\n            'collect_content_rules' => $collect_content_rules,\n            'collect_image_attribute' => $collect_image_attribute,\n            'collect_custom_content' => json_encode(['head' => $collect_custom_content_head, 'foot' => $collect_custom_content_foot]),\n            'collect_keywords_replace_rule' => $collect_keywords_replace_rule,\n            'collect_keywords' => $collect_keywords,\n            'created_at' => current_time('mysql'),\n            'updated_at' => current_time('mysql'),\n        ];\n\n        // Tips: 优化掉\n        if (in_array($collect_name, FRC_ApiError::BUTTON_DISABLED)){\n            // add author name variable\n            if ($collect_name == '微信'){\n                $params['collect_content_rules'] = $params['collect_content_rules'].')(author%#js_author_name|text|null)(name%#js_name|text|null';\n            } elseif ($collect_name == '简书'){\n                $params['collect_content_rules'] = $params['collect_content_rules'].')(author%span[class=name]|text|null';\n            }\n        }\n\n        if ($option_id === null){\n            if (in_array($collect_name, FRC_ApiError::BUTTON_DISABLED)){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => '不可使用这个配置名称！'];\n            }\n            if ($this->wpdb->insert($this->table_options, $params)) {\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => 'Creating Success.'];\n            } else {\n\t            $error = $this->wpdb->last_error;\n                return ['code' => FRC_ApiError::FAIL, 'msg' => 'Creating error. ' . $error];\n            }\n        }\n        if (false !== $this->wpdb->update($this->table_options, $params, ['id' => $option_id], ['%s', '%s'], ['%d'])) {\n            return ['code' => FRC_ApiError::SUCCESS, 'msg' => ' Update Success.'];\n        } else {\n\t        $error = $this->wpdb->last_error;\n            return ['code' => FRC_ApiError::FAIL, 'msg' => 'Update error. ' . $error];\n        }\n\n    }\n\n\n    /**\n     * @return array\n     */\n    public function interface_save_option_release(){\n\n        $option_id = frc_sanitize_text('option_id', null);\n\n        if (!$option_id){\n            return ['code' => FRC_ApiError::SUCCESS, 'msg' => 'option id error.'];\n        }\n\n        $msg = '保存完成.';\n        if (get_option(FRC_Validation::FRC_VALIDATION_RELEASE_CONTROL)){\n            $params = [\n                'category' => frc_sanitize_array('release_category', 'integer'),\n                'user' => frc_sanitize_array('release_user', 'integer'),\n                'status' => frc_sanitize_text('release_status', 'pending'),\n                'type' => frc_sanitize_text('release_type', 'post'),\n                'thumbnail' => frc_sanitize_text('release_thumbnail', 'thumbnail1'),\n                'release_type' => frc_sanitize_text('release_type', 'WordPress'),\n                'extension_field' => frc_sanitize_text('extension_field', 'post'),\n            ];\n\n            if (empty($params['category'])){\n                $params['category'] = array(1);\n            }\n\n            if (empty($params['user'])){\n                $params['user'] = [get_current_user_id()];\n            }\n        } else {\n            $msg = FRC_Validation::FRC_HINT_L;\n            $params = [\n                'category' => array(1),\n                'user' => [get_current_user_id()],\n                'status' => frc_sanitize_text('release_status', 'pending'),\n                'thumbnail' => 'thumbnail2',\n                'release_type' => 'WordPress',\n                'type' => 'post',\n                'extension_field' => 'post',\n            ];\n        }\n\n        $result = $this->wpdb->update($this->table_options,\n            ['collect_release' => json_encode($params)],\n            ['id' => $option_id],\n            ['%s', '%s'],\n            ['%d']\n        );\n\n        return ['code' => FRC_ApiError::SUCCESS, 'msg' => $msg, 'data' => $result];\n    }\n\n\n    /**\n     * @return array\n     */\n    public function interface_import_default_configuration(){\n\n        $default_configurations = collect([\n            [\n                'collect_name' => '胖鼠采集-御龙在天',\n                'collect_describe' => '列表采集规则, 页面编码GBK 小提示 如果class有两个属性,选一个唯一的即可 | ul li 中间还可以加空格哦知道什么意思吗?',\n                'collect_type' => 'list',\n                'collect_list_url' => 'https://yl.qq.com/webplat/info/news_version3/118/430/m279/list_1.shtml',\n                'collect_list_url_paging' => 'https://yl.qq.com/webplat/info/news_version3/118/430/m279/list_{page}.shtml',\n                'collect_list_range' => '.news_list ul li',\n                'collect_list_rules' => 'link%a:eq(1)|href|null',\n                'collect_content_range' => '.center_part',\n                'collect_content_rules' => 'title%.news_h2|text|null)(content%.news_content|html|null',\n                'collect_image_attribute' => 'src',\n                'collect_remove_head' => '2',\n                'collect_charset' => 'gbk',\n                'collect_custom_content' => '{\"head\":\"\",\"foot\":\"\"}',\n                'created_at' => current_time('mysql'),\n                'updated_at' => current_time('mysql'),\n            ],\n            [\n                'collect_name' => '胖鼠采集-寻仙',\n                'collect_describe' => '列表采集规则, 页面编码GBK, 曾经玩过这个游戏至今念念不忘. 小提示 仔细看配置 选择元素第二个a标签用 eq 语法',\n                'collect_type' => 'list',\n                'collect_list_url' => 'https://xx.qq.com/webplat/info/news_version3/154/2233/3889/m2702/list_1.shtml',\n                'collect_list_url_paging' => 'https://xx.qq.com/webplat/info/news_version3/154/2233/3889/m2702/list_{page}.shtml',\n                'collect_list_range' => '.down-nr>ul>li',\n                'collect_list_rules' => 'link%a:eq(1)|href|null',\n                'collect_content_range' => '.sub-cont',\n                'collect_content_rules' => 'title%.n_title|text|null)(content%.sub-nr|html|null',\n                'collect_image_attribute' => 'src',\n                'collect_remove_head' => '3',\n                'collect_charset' => 'gbk',\n                'collect_custom_content' => '{\"head\":\"\",\"foot\":\"\"}',\n                'created_at' => current_time('mysql'),\n                'updated_at' => current_time('mysql'),\n            ],\n            [\n                'collect_name' => '胖鼠采集-虎扑',\n                'collect_describe' => '地址: https://voice.hupu.com/sports',\n                'collect_type' => 'single',\n                'collect_content_range' => '.voice-main',\n                'collect_content_rules' => 'title%.artical-title>h1|text|null)(content%.artical-content|html|null',\n                'collect_image_attribute' => 'src',\n                'collect_remove_head' => '1',\n                'collect_charset' => 'utf-8',\n                'collect_custom_content' => '{\"head\":\"\",\"foot\":\"\"}',\n                'created_at' => current_time('mysql'),\n                'updated_at' => current_time('mysql'),\n            ],\n            [\n                'collect_name' => '胖鼠采集-直播8',\n                'collect_describe' => '地址: https://news.zhibo8.cc/nba/more.htm',\n                'collect_type' => 'single',\n                'collect_content_range' => '#main',\n                'collect_content_rules' => 'title%h1|text|null)(content%div[class=content]|html|null',\n                'collect_image_attribute' => 'src',\n                'collect_remove_head' => '1',\n                'collect_charset' => 'utf-8',\n                'collect_custom_content' => '{\"head\":\"\",\"foot\":\"\"}',\n                'created_at' => current_time('mysql'),\n                'updated_at' => current_time('mysql'),\n            ],\n            [\n                'collect_name' => '胖鼠采集-小故事',\n                'collect_describe' => '内容分页采集例子 http://www.xigushi.com/aqgs/3262.html',\n                'collect_type' => 'single',\n                'collect_content_range' => '.by',\n                'collect_content_rules' => 'title%h1|text|null)(content%dl>dd>p|html|a)(paging%.page a:contains(下一页)|href|null',\n                'collect_image_attribute' => 'src',\n                'collect_remove_head' => '2',\n                'collect_charset' => 'utf-8',\n                'collect_custom_content' => '{\"head\":\"\",\"foot\":\"\"}',\n                'created_at' => current_time('mysql'),\n                'updated_at' => current_time('mysql'),\n            ],\n        ]);\n\n        $default_configurations->map(function($default_config){\n            if (!$this->wpdb->get_row(\n                $this->wpdb->prepare(\"SELECT * FROM $this->table_options WHERE `collect_name` = %s limit 1\", $default_config['collect_name'])\n                , ARRAY_A\n            )){\n                $this->wpdb->insert($this->table_options, $default_config, ['%s', '%s']);\n            }\n        });\n\n        return ['code' => FRC_ApiError::SUCCESS, 'msg' => '完成, 快来走进胖鼠采集的世界吧. '];\n    }\n\n\n    /**\n     * @return array\n     */\n    public function interface_del_option(){\n\n        if(!current_user_can( 'manage_options' )){\n            wp_send_json(['code' => 5006, 'msg' => FRC_Validation::FRC_HINT_M]);\n            wp_die();\n        }\n\n        $option_id = frc_sanitize_text('option_id', null);\n        if (empty($option_id)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '配置ID错误'];\n        }\n\n        return ['code' => FRC_ApiError::SUCCESS, 'msg' => '删除成功', 'data' => $this->delete($option_id)];\n    }\n\n\n    /**\n     * @return array\n     */\n    public function interface_upgrade(){\n        if ('upgrade complete' == get_option('frc_mysql_upgrade')){\n            return ['code' => FRC_ApiError::SUCCESS, 'msg' => '升级完成'];\n        }\n\n        $progress = frc_sanitize_text('progress');\n        if ($progress == '1'){\n            $former_table_options = $this->wpdb->prefix . 'fr_options';\n            $res = $this->wpdb->get_results(\"SHOW TABLES LIKE '%{$former_table_options}%'\");\n            if (empty($res)){\n                update_option('frc_mysql_upgrade', '2');\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => '配置表升级完成.'];\n            }\n\n            $data = $this->wpdb->get_results(\"select * from $former_table_options\", ARRAY_A);\n            foreach ($data as $option){\n\n                $params = [\n                    'id' => $option['id'],\n                    'collect_name' => $option['collect_name'],\n                    'collect_describe' => $option['collect_describe'],\n                    'collect_type' => $option['collect_type'],\n                    'collect_cookie' => $option['collect_cookie'],\n                    'collect_rendering' => 1,\n                    'collect_image_download' => $option['collect_image_download'],\n                    'collect_image_path' => $option['collect_image_path'],\n                    'collect_remove_head' => ($option['collect_remove_head'] == 0) ? 1 : 2,\n                    'collect_list_url' => $option['collect_list_url'],\n                    'collect_list_url_paging' => '',\n                    'collect_list_range' => $option['collect_list_range'],\n                    'collect_list_rules' => $option['collect_list_rules'],\n                    'collect_content_range' => $option['collect_content_range'],\n                    'collect_content_rules' => $option['collect_content_rules'],\n                    'collect_image_attribute' => $option['collect_image_attribute'],\n                    'collect_custom_content' => $option['collect_custom_content'],\n                    'collect_keywords_replace_rule' => $option['collect_keywords_replace_rule'],\n                    'collect_charset' => $option['collect_charset'],\n                    'created_at' => $option['created'],\n                    'updated_at' => $option['created'],\n                ];\n\n                $this->wpdb->insert($this->table_options, $params);\n            }\n\n            update_option('frc_mysql_upgrade', '2');\n            //$this->wpdb->query( \"DROP TABLE IF EXISTS $former_table_options\" );\n            return ['code' => FRC_ApiError::SUCCESS, 'msg' => '配置系统、升级完成.'];\n        }\n        if ($progress == '2'){\n            $former_table_post = $this->wpdb->prefix . 'fr_post';\n            $res = $this->wpdb->get_results(\"SHOW TABLES LIKE '%{$former_table_post}%'\");\n            if (empty($res)){\n                update_option('frc_mysql_upgrade', 'upgrade complete');\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => '升级完成.'];\n            }\n\n            try{\n                $last_id = get_option('frc_mysql_upgrade_progress', 0);\n                $data = $this->wpdb->get_results($this->wpdb->prepare(\"select `id`, `title`, `content`, `image`, `post_type`, `link`, `post_id`, `is_post`, `created`  from $former_table_post where id > %d limit 500\", $last_id), ARRAY_A);\n                if (empty($data)){\n                    delete_option('frc_mysql_upgrade_progress');\n                    update_option('frc_mysql_upgrade', 'upgrade complete');\n                    //$this->wpdb->query( \"DROP TABLE IF EXISTS $former_table_post\" );\n                    return ['code' => FRC_ApiError::SUCCESS, 'msg' => '数据系统，升级完成.'];\n                }\n\n                foreach ($data as $post){\n                    $params = [\n                        'id' => $post['id'],\n                        'option_id' => $post['post_type'],\n                        'status' => ($post['is_post'] == 0) ? 2 : 3,\n                        'title' => $post['title'],\n                        'cover' => $post['image'],\n                        'content' => $post['content'],\n                        'link' => $post['link'],\n                        'post_id' => $post['post_id'],\n                        'message' => 'migration data.',\n                        'created_at' => $post['created'],\n                        'updated_at' => $post['created'],\n                    ];\n\n                    try{\n                        $this->wpdb->replace($this->wpdb->prefix.'frc_post', $params);\n                    } catch (Exception $e){\n                    }\n\n                }\n\n                $last_id = update_option('frc_mysql_upgrade_progress', end($data)['id']);\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => '数据系统，分段升级进行中, 分段升级市为避免大数据量鼠升级失败提供的, 目前已经升级进度'.$last_id.'条, 请继续点击红色按钮进行下一段升级'];\n\n            } catch (Exception $e) {\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => '异常，数据导入失败.'];\n            }\n        }\n\n        return ['code' => FRC_ApiError::SUCCESS, 'msg' => '升级完成'];\n    }\n\n\n    /**\n     * @return array\n     */\n    public function interface_update_auto_config(){\n        $option = frc_sanitize_text('option');\n        $value = frc_sanitize_text('value');\n\n        if (empty($option)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => 'Operation Key Error!'];\n        }\n        if (!strstr($option, 'frc_')){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => 'Off the white list.'];\n        }\n\n        $data = update_option($option, $value);\n        wp_clear_scheduled_hook($option.'_hook');\n        return ['code' => FRC_ApiError::SUCCESS, 'msg' => '设置完成.', 'data' => $data];\n    }\n}\n\nclass FRC_Configuration_List_Table extends WP_List_Table\n{\n    /**\n     * Retrieve snippets data from the database\n     *\n     * @param int $per_page\n     * @param int $page_number\n     *\n     * @return mixed\n     */\n    public static function get_snippets($per_page = 10, $page_number = 1, $customvar = 'total')\n    {\n        $model = new FRC_Options();\n        $result = $model->options_paging($page_number, $per_page, $customvar);\n        return collect($result)->map(function ($data){\n            $data['collect_auto_collect'] = '完善中';\n            $data['collect_auto_release'] = '完善中';\n            return $data;\n        });\n    }\n\n    /**\n     * Delete a snipppet record.\n     * @param $id\n     * @return false|int\n     */\n    public function delete_snippet($id)\n    {\n        $model = new FRC_Options();\n        return $model->delete($id);\n    }\n\n    /**\n     * Activate a snipppet record.\n     *\n     * @param int $id snippet ID\n     */\n    public static function activate_snippet($id)\n    {\n\n    }\n\n    /**\n     * Deactivate a snipppet record.\n     *\n     * @param int $id snippet ID\n     */\n    public static function deactivate_snippet($id)\n    {\n\n    }\n\n    /**\n     * Returns the count of records in the database.\n     *\n     * @return null|string\n     */\n    public static function record_count($customvar = 'total')\n    {\n        $model = new FRC_Options();\n        return $model->record_count($customvar);\n    }\n\n    /** Text displayed when no snippet data is available */\n    public function no_items()\n    {\n        esc_html_e('配置空空的, 请创建采集配置开始旅程吧, 如果你快速认识胖鼠, 可以使用上面一键导入默认配置来学习.', 'Fat Rat Collect');\n    }\n\n    /**\n     * Render a column when no column specific method exist.\n     *\n     * @param array $item\n     * @param string $column_name\n     *\n     * @return mixed\n     */\n    public function column_default($item, $column_name)\n    {\n        switch ($column_name) {\n            case 'collect_image_download' :\n                switch ($item[$column_name]){\n                    case '1':\n                        return esc_html('下载到本地');\n                        break;\n                    case '2':\n                        return esc_html('不下载');\n                        break;\n                    case '3':\n                        return esc_html('清除所有图片');\n                        break;\n                }\n                break;\n            case 'collect_image_path' :\n                switch ($item[$column_name]){\n                    case '1':\n                        return esc_html('绝对路径');\n                        break;\n                    case '2':\n                        return esc_html('相对路径');\n                        break;\n                }\n            case 'collect_list_url' :\n                return sprintf(\"<a href='%s' target='_blank'>%s</a>\", $item[$column_name], $item[$column_name]);\n                break;\n            case 'collect_describe':\n                return esc_html(mb_substr($item[$column_name], 0, 30) . ' ...');\n                break;\n            case 'collect_type' :\n                switch ($item[$column_name]){\n                    case 'list':\n                        return esc_html('列表采集');\n                        break;\n                    case 'single':\n                        return esc_html('详情采集');\n                        break;\n                    case 'all':\n                        return esc_html('全站采集');\n                        break;\n                    case 'keyword':\n                        return esc_html('关键字采集');\n                        break;\n                }\n                break;\n            case 'collect_name':\n                $title = '<strong>' . $item['collect_name'] . '</strong>';\n                $actions = array(\n                    '修改' => sprintf(\"<a href='%s'>%s</a>\", admin_url('admin.php?page=frc-options-add-edit&option_id=' . $item['id']), esc_html__('修改', 'Fat Rat Collect')),\n                    '删除' => sprintf(\"<a href='javascript:;'><span class='delete-option-button' data-value='%s'>%s</span></a>\", $item['id'], esc_html__('删除', 'Fat Rat Collect')),\n                );\n                return $title . $this->row_actions( $actions );\n                break;\n            case 'collect_keywords_replace_rule' :\n                return esc_html('... 点击查看');\n                break;\n            default:\n                return esc_html($item[$column_name]);\n                break;\n        }\n    }\n\n    /**\n     * Render the bulk edit checkbox\n     *\n     * @param array $item\n     *\n     * @return string\n     */\n    function column_cb($item)\n    {\n        return sprintf(\n            '<input type=\"checkbox\" name=\"snippets[]\" value=\"%s\" />', $item['id']\n        );\n    }\n\n    /**\n     * Method for name column\n     *\n     * @param array $item an array of DB data\n     *\n     * @return string\n     */\n    function column_name($item)\n    {\n\n    }\n\n    /**\n     *  Associative array of columns\n     *\n     * @return array\n     */\n    function get_columns()\n    {\n        $columns = array(\n            'cb' => '<input type=\"checkbox\" />',\n            'id' => esc_html__('ID', 'Fat Rat Collect'),\n            'collect_name' => esc_html__('配置名称', 'Fat Rat Collect'),\n            'collect_describe' => esc_html__('配置描述', 'Fat Rat Collect'),\n            'collect_type' => esc_html__('采集类型', 'Fat Rat Collect'),\n            'collect_list_url' => esc_html__('采集地址', 'Fat Rat Collect'),\n//            'collect_auto_collect' => esc_html__('自动采集', 'Fat Rat Collect'),\n//            'collect_auto_release' => esc_html__('自动发布', 'Fat Rat Collect'),\n            'collect_list_url' => esc_html__('采集地址', 'Fat Rat Collect'),\n            'collect_image_download' => esc_html__('下载图片', 'Fat Rat Collect'),\n            'collect_image_path' => esc_html__('图片使用路径', 'Fat Rat Collect'),\n            'collect_image_attribute' => esc_html__('目标图片源属性', 'Fat Rat Collect'),\n            'created_at' => esc_html__('创建时间', 'Fat Rat Collect'),\n        );\n\n        return $columns;\n    }\n\n    /**\n     * Columns to make sortable.\n     *\n     * @return array\n     */\n    public function get_sortable_columns()\n    {\n\n        return array(\n            'id' => array('id', false),\n        );\n    }\n\n    /**\n     * Returns an associative array containing the bulk action\n     *\n     * @return array\n     */\n    public function get_bulk_actions()\n    {\n\n        return array(\n            'bulk-todo' => esc_html__('敬请期待', 'Fat Rat Collect'),\n//            'bulk-start-collect' => esc_html__('开启自动采集', 'Fat Rat Collect'),\n//            'bulk-stop-collect' => esc_html__('关闭自动采集', 'Fat Rat Collect'),\n//            'bulk-start-release' => esc_html__('开启自动采集', 'Fat Rat Collect'),\n//            'bulk-stop-release' => esc_html__('关闭自动采集', 'Fat Rat Collect'),\n        );\n    }\n\n    /**\n     * Handles data query and filter, sorting, and pagination.\n     */\n    public function prepare_items()\n    {\n\n        $columns = $this->get_columns();\n        $hidden = array();\n        $sortable = $this->get_sortable_columns();\n\n        //Retrieve $customvar for use in query to get items.\n        $customvar = frc_sanitize_text('customvar', 'total');\n        $this->_column_headers = array($columns, $hidden, $sortable);\n\n        /** Process bulk action */\n        $this->process_bulk_action();\n        $this->views();\n        $per_page = $this->get_items_per_page('snippets_per_page', 10);\n        $current_page = $this->get_pagenum();\n        $total_items = self::record_count();\n\n        $this->set_pagination_args(array(\n            'total_items' => $total_items,\n            'per_page' => $per_page,\n        ));\n\n        $this->items = self::get_snippets($per_page, $current_page, $customvar);\n    }\n\n\tpublic function get_views()\n\t{\n\t\t$views = array();\n\t\t$current = frc_sanitize_text('customvar', 'total'); // 假设这里的 `frc_sanitize_text` 已确保安全\n\n\t\t// 总计\n\t\t$class = 'total' === $current ? ' class=\"current\"' : '';\n\t\t$total_url = esc_url(remove_query_arg('customvar')); // 转义 URL\n\t\t$views['total'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$total_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('全部配置', 'Fat Rat Collect'),\n\t\t\t$this->record_count()\n\t\t);\n\n\t\t// 列表采集\n\t\t$foo_url = esc_url(add_query_arg('customvar', 'list')); // 转义 URL\n\t\t$class = ('list' === $current ? ' class=\"current\"' : '');\n\t\t$views['list'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$foo_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('列表采集', 'Fat Rat Collect'),\n\t\t\t$this->record_count('list')\n\t\t);\n\n\t\t// 详情采集\n\t\t$bar_url = esc_url(add_query_arg('customvar', 'single')); // 转义 URL\n\t\t$class = ('single' === $current ? ' class=\"current\"' : '');\n\t\t$views['single'] = sprintf(\n\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t$bar_url,\n\t\t\tesc_attr($class),\n\t\t\tesc_html__('详情采集', 'Fat Rat Collect'),\n\t\t\t$this->record_count('single')\n\t\t);\n\n\t\t// 全站采集（可选）\n\t\tif (get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT)) {\n\t\t\t$all_url = esc_url(add_query_arg('customvar', 'all')); // 转义 URL\n\t\t\t$class = ('all' === $current ? ' class=\"current\"' : '');\n\t\t\t$views['all'] = sprintf(\n\t\t\t\t'<a href=\"%s\"%s>%s (%d)</a>',\n\t\t\t\t$all_url,\n\t\t\t\tesc_attr($class),\n\t\t\t\tesc_html__('全站采集', 'Fat Rat Collect'),\n\t\t\t\t$this->record_count('all')\n\t\t\t);\n\t\t}\n\n\t\treturn $views;\n\t}\n\n\tpublic function process_bulk_action()\n    {\n        // If the delete bulk action is triggered\n        if (\n            ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) ||\n            ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] )\n        ) {\n//            $delete_ids = esc_sql( $_POST['snippets'] );\n//\n//            // loop over the array of record IDs and delete them\n//            foreach ( $delete_ids as $id ) {\n//                $this->delete_snippet( $id );\n//            }\n//\n//            return;\n        }\n    }\n}\n\n\nfunction frc_options()\n{\n    $snippet_obj = new FRC_Configuration_List_Table();\n    ?>\n    <div class=\"wrap\">\n        <h1><?php esc_html_e( '配置中心', 'Fat Rat Collect' ) ?>\n            <?php if (!empty(get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP))) { ?>\n                <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png') ?>\" />\n            <?php } ?>\n            <a href=\"<?php esc_attr_e(admin_url( 'admin.php?page=frc-options-add-edit' )); ?>\" class=\"page-title-action\"><?php _e( '新建采集配置', 'Fat Rat Collect' ) ?></a>\n            <a href=\"javascript:\" class=\"page-title-action import_default_configuration\"><?php _e( '演示例子', 'Fat Rat Collect' ) ?></a>\n        </h1>\n        <div><span style=\"color: #ff3d00;\"><?php _e(((new FRC_Validation())->announcement('notice-options'))); ?></span></div>\n        <input type=\"hidden\" hidden id=\"success_redirect_url\"\n               value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-options')); ?>\">\n\n        <form method=\"post\">\n            <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n\t        <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n            <?php\n            $snippet_obj->prepare_items();\n            $snippet_obj->display();\n            ?>\n        </form>\n\n    </div>\n    <?php\n}\n\n"
  },
  {
    "path": "includes/fatrat-spider.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: FatRat\n * @CreateTime: 2018年12月30日 02:24\n */\n\nif (!class_exists('AbsoluteUrl')) {\n    require_once(plugin_dir_path(__DIR__) . 'src/Service/AbsoluteUrl.php');\n}\nif (!class_exists('DownloadImage')) {\n    require_once(plugin_dir_path(__DIR__) . 'src/Service/DownloadImage.php');\n}\nif (!class_exists('GetTransCoding')) {\n    require_once(plugin_dir_path(__DIR__) . 'src/Service/GetTransCoding.php');\n}\n\nuse Nesk\\Rialto\\Data\\JsFunction;\nuse QL\\Ext\\AbsoluteUrl;\nuse QL\\Ext\\Chrome;\nuse QL\\Ext\\DownloadImage;\nuse QL\\Ext\\GetTransCoding;\nuse QL\\QueryList;\n\nclass FRC_Spider\n{\n    protected $wpdb;\n    protected $table_post;\n\n    public function __construct()\n    {\n        global $wpdb;\n        $this->wpdb = $wpdb;\n        $this->table_post = $wpdb->prefix . 'frc_post';\n    }\n\n\n    /**\n     * 懒人采集\n     * @return array\n     */\n    public function grab_custom_page(){\n        $urls = frc_sanitize_text('collect_urls');\n        $name = frc_sanitize_text('collect_name');\n\n        if (empty($urls)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '链接不能为空'];\n        }\n        if (empty($name) || !in_array($name, ['wx', 'js', 'zh'])){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '链接不能为空'];\n        }\n\n        switch ($name){\n            case 'wx':\n                $name = '微信';\n                $urls = $this->wx_url_format($urls);\n                break;\n            case 'js':\n                $name = '简书';\n                break;\n            case 'zh':\n                $name = '知乎';\n                break;\n        }\n\n        $options = new FRC_Options();\n        $option = $options->lazy_person($name);\n\n        return $this->response(FRC_ApiError::SUCCESS, $this->single_spider($option, $urls), $name .'数据处理完成, F12可查看单条数据具体采集结果喔');\n    }\n\n    private function wx_url_format($urls){\n        $urls = explode(' ', $urls);\n        foreach ($urls as &$url){\n            $i = strpos($url, '&chksm');\n            if ($i === false){\n                continue;\n            }\n            $url = substr($url, 0, $i);\n        }\n\n        return join(' ', $urls);\n    }\n\n    /**\n     * 抓取详情\n     * @return array\n     */\n    public function grab_details_page(){\n        $urls       = frc_sanitize_text('collect_details_urls');\n        $option_id  = frc_sanitize_text('collect_details_relus', 0);\n        if (empty($urls)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '链接不能为空'];\n        }\n        if (empty($option_id)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '请选择一个有效的详情配置'];\n        }\n        $options = new FRC_Options();\n        $option = $options->option($option_id);\n        if (!$option) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '未查询到配置, 配置ID错误'];\n        }\n\n        return $this->response(FRC_ApiError::SUCCESS, $this->single_spider($option, $urls));\n    }\n\n\n    /**\n     * 列表采集\n     * @return array\n     */\n    public function grab_list_page()\n    {\n        $option_id = frc_sanitize_text('option_id', 0);\n\n        $options = new FRC_Options();\n        $option = $options->option($option_id);\n        if (!$option) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '未查询到配置, 配置ID错误'];\n        }\n\n        $config = new stdClass();\n        $config->url = $option['collect_list_url'];\n        $config->range = $option['collect_list_range'];\n        $config->rules = $this->rulesFormat($option['collect_list_rules']);\n        $config->rendering = $option['collect_rendering'];\n        $config->remove_head = $option['collect_remove_head'];\n        $config->image_download = $option['collect_image_download'];\n        $config->image_path = $option['collect_image_path'];\n        $config->src = $option['collect_image_attribute'];\n        isset($option[\"collect_cookie\"]) && $config->cookie = $option[\"collect_cookie\"];\n\n        $articles = $this->_QlObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) {\n            if ($this->checkPostLink($item['link'])){\n                return $this->format($item, '已滤重');\n            }\n\n            $config->url = $item['link'];\n            $config->range = $option['collect_content_range'];\n            $config->rules = $this->rulesFormat($option['collect_content_rules']);\n            $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->special($config)->query()->getDataAndRelease();\n            $detail = array_merge($item, empty($detail)?[]:current($detail));\n            $this->paging($detail, $config);\n            return $this->insert_article($detail, $option);\n        })->getDataAndRelease();\n\n        return $this->response(FRC_ApiError::SUCCESS, $articles, '列表采集完成');\n    }\n\n\n    /**\n     * 历史(分页)页面\n     */\n    public function grab_history_page()\n    {\n        $history_page_number    = frc_sanitize_text('collect_history_page_number');\n        $option_id              = frc_sanitize_text('collect_history_relus_id', null);\n        if ($option_id === null){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '请选择一个配置'];\n        }\n        $options = new FRC_Options();\n        $option = $options->option($option_id);\n        if (!$option) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '请选择一个有效的配置, 配置异常'];\n        }\n\n        if (empty($history_page_number)){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '请填写页码/翻页'];\n        }\n\n        if (empty($option['collect_list_url_paging'])){\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '请配置分页采集地址'];\n        }\n\n        if ($option['collect_rendering'] == 1){\n\n            if (!strstr($option['collect_list_url_paging'], '{page}')){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => 'URL不正确。未包含 {page} 关键字 or URL不能为空'];\n            }\n\n            $page_count = explode('-', $history_page_number);\n            $page_count = count($page_count) == 2 ? range($page_count[0], $page_count[1]) : [(int)$page_count[0]];\n\n            if (!get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP) && count($page_count) > 3){\n                return ['code' => FRC_ApiError::FAIL, 'msg' => FRC_Validation::FRC_HINT_F];\n            }\n\n            $articles = collect($page_count)->map(function($digital) use ($option){\n                $config = new stdClass();\n                $config->url = $option['collect_list_url_paging'];\n                $config->range = $option['collect_list_range'];\n                $config->rules = $this->rulesFormat($option['collect_list_rules']);\n                $config->rendering = $option['collect_rendering'];\n                $config->remove_head = $option['collect_remove_head'];\n                $config->image_download = $option['collect_image_download'];\n                $config->image_path = $option['collect_image_path'];\n                $config->src = $option['collect_image_attribute'];\n                $config->pn = $digital;\n\n                $result['url'] = str_replace('{page}', $config->pn, $config->url);\n                $article = $this->_QlPagingObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) {\n                    if ($this->checkPostLink($item['link'])){\n                        return $this->format($item, '已滤重');\n                    }\n\n                    $config->url = $item['link'];\n                    $config->range = $option['collect_content_range'];\n                    $config->rules = $this->rulesFormat($option['collect_content_rules']);\n                    $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->special($config)->query()->getDataAndRelease();\n                    $detail = array_merge($item, empty($detail)?[]:current($detail));\n                    $this->paging($detail, $config);\n                    return $this->insert_article($detail, $option);\n                })->getDataAndRelease();\n                $result['data'] = $article;\n                return $result;\n            });\n        } else {\n            $config = new stdClass();\n            $config->url = $option['collect_list_url'];\n            $config->range = $option['collect_list_range'];\n            $config->rules = $this->rulesFormat($option['collect_list_rules']);\n            $config->rendering = $option['collect_rendering'];\n            $config->remove_head = $option['collect_remove_head'];\n            $config->image_download = $option['collect_image_download'];\n            $config->image_path = $option['collect_image_path'];\n            $config->src = $option['collect_image_attribute'];\n            $config->pn = $history_page_number;\n            $article = $this->_QlPagingObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) {\n                if ($this->checkPostLink($item['link'])){\n                    return $this->format($item, '已滤重');\n                }\n\n                $config->url = $item['link'];\n                $config->range = $option['collect_content_range'];\n                $config->rules = $this->rulesFormat($option['collect_content_rules']);\n                $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->query()->getDataAndRelease();\n                $detail = array_merge($item, current($detail)??'');\n                $this->paging($detail, $config);\n                return $this->insert_article($detail, $option);\n            })->getDataAndRelease();\n            $articles['rolling'] = $history_page_number;\n            $articles['data'] = $article;\n        }\n\n        return $this->response(FRC_ApiError::SUCCESS, $articles, '分页采集完成');\n    }\n\n\n    /**\n     * @return array\n     */\n    public function grab_all_page()\n    {\n        $option_id = frc_sanitize_text('option_id', 0);\n\n        $options = new FRC_Options();\n        $option = $options->option($option_id);\n        if (!$option) {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => '未查询到配置, 配置ID错误'];\n        }\n\n        $config = new stdClass();\n        $config->url = $option['collect_list_url'];\n        $config->range = $option['collect_list_range'];\n        //$config->rules = $this->rulesFormat($option['collect_list_rules']);\n        $config->rendering = $option['collect_rendering'];\n        $config->remove_head = $option['collect_remove_head'];\n        $config->image_download = $option['collect_image_download'];\n        $config->image_path = $option['collect_image_path'];\n        $config->src = $option['collect_image_attribute'];\n        $config->pure = true;\n\n        // TODO: 优化内存使用\n        $articles = $this->_QlObject($config)->absoluteUrl($config)->find('a')->attrs('href')->filter(function ($item) use ($config) {\n            if ($item === null){\n                return false;\n            }\n\n\t        $config->range = str_replace(\"\\\\\\\\\", \"\\\\\", htmlspecialchars_decode($config->range));\n            $pattern = '/'.str_replace('/', '\\/', $config->range).'/';\n            if (preg_match($pattern, $item, $matches)){\n                return true;\n            }\n\n            return false;\n        });\n\n        $articles = $articles->map(function ($link) use ($config, $option) {\n            $item['link'] = $link;\n            if ($this->checkPostLink($item['link'])){\n                return $this->format($item, '已滤重');\n            }\n            $config->url = $item['link'];\n            $config->range = $option['collect_content_range'];\n            $config->rules = $this->rulesFormat($option['collect_content_rules']);\n            $config->pure = false;\n            $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->query()->getDataAndRelease();\n            $detail = array_merge($item, empty($detail)?[]:current($detail));\n            $this->paging($detail, $config);\n            return $this->insert_article($detail, $option);\n        });\n\n        return $this->response(FRC_ApiError::SUCCESS, $articles, '全站采集完成');\n    }\n\n\n    /**\n     * @return array\n     */\n    public function grab_debug(){\n        $config = new stdClass();\n        $config->url = frc_sanitize_text('debug_url');\n        $config->range = frc_sanitize_text('debug_range');\n        $config->rules = $this->rulesFormat(frc_sanitize_text('debug_rules'));\n        $config->rendering = frc_sanitize_text('debug_rendering', 1);\n        $config->remove_head = frc_sanitize_text('debug_remove_head', 1);\n\n        if (empty($config->url)){\n            return $this->response(FRC_ApiError::SUCCESS, null, '请输入参数.');\n        }\n\n        $detail = $this->_QlObject($config)->absoluteUrl($config)->query()->getDataAndRelease();\n\n        return $this->response(FRC_ApiError::SUCCESS, $detail, '调试完成, 请在F12中查看');\n    }\n\n\n    /**\n     * 微信公众号历史文章采集\n     */\n    function grab_wechat_history()\n    {\n        $appName = frc_sanitize_text('collect_wechat_app_name');\n        $startNumber = frc_sanitize_text('collect_wechat_app_start_number');\n        $page = frc_sanitize_text('collect_wechat_app_number');\n        $cookie = frc_sanitize_text('collect_wx_app_cookie');\n        $token = frc_sanitize_text('collect_wx_app_token');\n\n        $auth = get_option('frc_validation_wechat_history');\n        if (empty($auth))  return $this->response(FRC_ApiError::FAIL, null, '激'.'活后才'.'能使'.'用哦');\n        $auth = json_decode($auth,true);\n        //if (isset($auth['expireDate']) && time() > $auth['expireDate']) return $this->response(FRC_ApiError::FAIL, null, '试用结束啦，请赞赏后试用～');\n\n        if (empty($appName) || empty($startNumber) || empty($page) || empty($cookie) || empty($token)) return $this->response(FRC_ApiError::FAIL, null, '请检查提交参数，所有参数均不可为空');\n\n        if ($page > 30) return $this->response(FRC_ApiError::FAIL, null, '为保护鼠友账号安全，单次采集最大页数暂定不超过30页');\n\n        $cookie = explode(\"; \",$cookie);\n        $cookieData = [];\n        foreach ($cookie as $item) {\n            $item = explode(\"=\",$item);\n            $cookieData[$item[0]] = isset($item[1]) ? $item[1] : \"\";\n        }\n\n        $cookieJar = \\GuzzleHttp\\Cookie\\CookieJar::fromArray($cookieData,\"mp.weixin.qq.com\");\n        $client = new \\GuzzleHttp\\Client();\n        //ps 优化点 这个fakeid 可以存在option里 不用每次都去查\n        $url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?action=search_biz&begin=0&count=5&token='.$token.'&lang=zh_CN&f=json&ajax=1&query='.urlencode($appName);\n        $result = $client->request(\"get\",$url,[\n            \"cookies\"=>$cookieJar\n        ])\n            ->getBody()\n            ->getContents();\n        if (!empty($result)) {\n            $result = json_decode($result,true);\n            if (!isset($result[\"base_resp\"][\"ret\"]) && $result[\"base_resp\"][\"ret\"] != 0) return $this->response(FRC_ApiError::FAIL, null, '请检查公众号名称是否有误，未搜索到相关公众号');\n            $list = $result[\"list\"];\n            $fakeId = '';\n            foreach ($list as $item) {\n                if ($item[\"nickname\"] == $appName)\n                {\n                    $fakeId = $item['fakeid'];\n                }\n            }\n            if (empty($fakeId))  return $this->response(FRC_ApiError::FAIL, null, '请检查公众号名称是否有误，未搜索到相关公众号');\n            $listUrl = 'https://mp.weixin.qq.com/cgi-bin/appmsgpublish?sub=list&search_field=null&';\n\n            $options = new FRC_Options();\n            $option = $options->lazy_person(\"微信\");\n\n            if (!$this->checkWechatHistoryTimeLimit($page)) return $this->response(FRC_ApiError::FAIL, null, '为保护鼠友公众号安全，单日采集最大页数不能超过500页');\n\n            for ($i = 0; $i < $page; $i++)\n            {\n                sleep(3);\n                $begin = $startNumber == 1 ? 0 : $startNumber * 20 + $i * 20;\n\n                $listUrl .= 'begin='.$begin.'&count=20&query=&fakeid='.$fakeId.'&type=101_1&free_publish_type=1&sub_action=list_ex&token='.$token.'&lang=zh_CN&f=json&ajax=1';\n\n                $result = $client->request(\"get\",$listUrl,[\n                    \"cookies\"=>$cookieJar\n                ])\n                    ->getBody()\n                    ->getContents();\n                if (!empty($result)) {\n                    $result = json_decode($result, true);\n                    if (!isset($result[\"base_resp\"][\"ret\"]) && $result[\"base_resp\"][\"ret\"] != 0) return $this->response(FRC_ApiError::FAIL, null, $result[\"base_resp\"][\"err_msg\"]);\n\n                    $publishPage = json_decode($result[\"publish_page\"],true);\n                    foreach ($publishPage[\"publish_list\"] as $item) {\n                        //每期发布的文章\n                        $articles = json_decode($item[\"publish_info\"],true)['appmsgex'];\n                        foreach ($articles as $article) {\n                            //每期的每一篇文章\n                            if ($this->checkPostLink($article['link'])) continue;\n\n                            $data['status'] = 1;\n                            $data['option_id'] = $option['id'];\n                            $data['cover'] = isset($article['cover']) ? $article['cover'] : '';\n                            $data['link'] = $article['link'];\n                            $data['title'] = mb_substr($this->text_keyword_replace($article['title'], $option), 0, 120);\n                            $data['content'] = \"\";\n                            $data['message'] = 'Wait.';\n                            $data['created_at'] = current_time('mysql');\n                            $data['updated_at'] = current_time('mysql');\n                            $this->wpdb->insert($this->table_post, $data);\n                        }\n                    }\n                    return $this->response(FRC_ApiError::SUCCESS, null, \"采集完成，请到数据桶查看\");\n                }else{\n                    return $this->response(FRC_ApiError::FAIL, null,  '网络错误, 请重试. ');\n                }\n            }\n        }else return $this->response(FRC_ApiError::FAIL, null,  '网络错误, 请重试. ');\n\n    }\n\n    /**\n     * @param $option\n     * @param $urls\n     * @return array|bool\n     */\n    public function single_spider($option, $urls)\n    {\n        if ($option['collect_type'] != 'single'){\n            return ['message' => '任务类型错误', 'data' => $option];\n        }\n\n        $config = new stdClass();\n        $config->url = '';\n        $config->range = $option['collect_content_range'];\n        $config->rules = $this->rulesFormat($option['collect_content_rules']);\n        $config->rendering = $option['collect_rendering'];\n        $config->remove_head = $option['collect_remove_head'];\n        $config->image_download = $option['collect_image_download'];\n        $config->image_path = $option['collect_image_path'];\n        $config->src = $option['collect_image_attribute'];\n\n        isset($option[\"collect_cookie\"]) && $config->cookie = $option[\"collect_cookie\"];\n        $article = collect(explode(' ', $urls))->map(function($url) use ($config, $option) {\n            $config->url = $url;\n            $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->special($config)->query()->getDataAndRelease();\n            $detail = array_merge(['link' => $url], (array)current($detail));\n            $this->paging($detail, $config);\n            $option[\"url\"] = $url;\n            return $this->insert_article($detail, $option);\n        });\n\n\n        return ['message' => '处理完成', 'data' => $article];\n    }\n\n\n    /**\n     * @param $detail\n     * @param $config\n     */\n    private function paging(&$detail, $config)\n    {\n        $i = 1;\n        $maximum = 50;\n        $detail['paging'] = AbsoluteUrl::urlFormat($detail['paging']??'', $config->url); // url format\n        if (!empty($detail['paging'])) {\n            $config->url = $detail['paging'];\n            while (true) {\n                $pagging = $this->_QlObject($config)\n                    ->absoluteUrl($config)\n                    ->downloadImage($config)\n                    ->special($config)\n                    ->query()->getDataAndRelease();\n                $pagging = current($pagging);\n                $pagging['paging'] = AbsoluteUrl::urlFormat($pagging['paging'], $config->url);\n                $detail['content'] .= $pagging['content'];\n                if (empty($pagging['paging']) || $pagging['paging'] == $config->url || $i > $maximum) {\n                    break;\n                }\n                $config->url = AbsoluteUrl::urlFormat($pagging['paging'], $config->url); // url format\n                $detail['paging_'.$i] = $config->url;\n                $i++;\n            }\n        }\n    }\n\n\n    /**\n     * @param $text\n     * @param $option\n     * @return mixed\n     */\n    private function text_keyword_replace($text, $option)\n    {\n        if (!$text || !$option) {\n            return $text;\n        }\n        $keywords_array = explode(\" \", trim($option['collect_keywords_replace_rule']));\n        collect($keywords_array)->map(function ($keywords) use (&$text) {\n            if (empty($keywords)){\n                return ;\n            }\n            list($string, $replace) = explode('=', $keywords);\n            $text = str_replace($string, $replace, $text);\n        });\n\n        return preg_replace('#<!--[^\\!\\[]*?(?<!\\/\\/)-->#' , '' , $text); // 去掉注释\n    }\n\n\n    /**\n     * 定时爬虫\n     * @return array\n     */\n    public function timing_spider()\n    {\n        $options = collect((new FRC_Options())->options());\n\n        $re = $options->reverse()->map(function ($option){\n            if ($option['collect_type'] == 'single'){\n                return $this->format($option, '详情采集不支持自动');\n            }\n\n            $config = new stdClass();\n            $config->url = $option['collect_list_url'];\n            $config->range = $option['collect_list_range'];\n            $config->rules = $this->rulesFormat($option['collect_list_rules']);\n            $config->rendering = $option['collect_rendering'];\n            $config->remove_head = $option['collect_remove_head'];\n            $config->image_download = $option['collect_image_download'];\n            $config->image_path = $option['collect_image_path'];\n            $config->src = $option['collect_image_attribute'];\n\n            // 采集列表\n            $articles = $this->_QlObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) {\n                if ($this->checkPostLink($item['link'])){\n                    return $this->format($item, '已滤重');\n                }\n\n                // 采集详情\n                $config->url = $item['link'];\n                $config->range = $option['collect_content_range'];\n                $config->rules = $this->rulesFormat($option['collect_content_rules']);\n                $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->query()->getDataAndRelease();\n                $detail = array_merge($item, empty($detail)?[]:current($detail));\n                $this->paging($detail, $config);\n\n                return $this->insert_article($detail, $option);\n            })->getDataAndRelease();\n\n            return $articles;\n        });\n\n        return ['message' => '处理完成', 'data' => $re];\n    }\n\n    /**\n     * @param $option\n     * @return QueryList\n     */\n    public function _QlObject($option)\n    {\n        $config = new \\stdClass;\n        $config->url = $option->url;\n        $config->range = $option->range;\n        $config->rules = $option->rules;\n        $config->rendering = $option->rendering;\n        $config->remove_head = $option->remove_head;\n        $config->pure = isset($option->pure) && $option->pure === true ? true : false;\n\n        $ql = $this->_QlInstance();\n        if (!$config->pure) {\n            $ql->rules($config->rules)->range($config->range);\n        }\n\n        $head = [\n            'timeout' => 100\n        ];\n        if ($option->cookie)\n        {\n            $head['headers'] = [\n                'Cookie'    => $option->cookie,\n            ];\n        }\n        try{\n            if ($config->rendering == 1) {\n                if ($config->remove_head == 3){\n                    $ql->getTransCoding($config->url);\n                } else {\n                    $ql->get( $config->url ,null, $head);\n                }\n            } elseif ($config->rendering == 2) {\n                $ql->use(Chrome::class);\n                $options = ['args' => ['--no-sandbox', '--disable-setuid-sandbox'], 'timeout' => 10000];\n                $ql->chrome($config->url, $options);\n            }\n        } catch (Exception $e){\n            $ql->setHtml('');\n            // http error\n        }\n        $ql->encoding('UTF-8');\n\n        if (strstr('2-3', $config->remove_head)) {\n            $ql->removeHead();\n        }\n\n        return $ql;\n    }\n\n\n    /**\n     * @param $option\n     * @return QueryList\n     */\n    public function _QlPagingObject($option)\n    {\n        $config = new \\stdClass;\n        $config->url = $option->url;\n        $config->range = $option->range;\n        $config->rules = $option->rules;\n        $config->rendering = $option->rendering;\n        $config->remove_head = $option->remove_head;\n        $config->pn = $option->pn;\n\n        $ql = $this->_QlInstance()->rules($config->rules)->range($config->range);\n\n        try{\n            if ($config->rendering == 1) {\n                $url = str_replace('{page}', $config->pn, $config->url);\n                if ($config->remove_head == 3){\n                    $ql->getTransCoding($url);\n                } else {\n                    $ql->get($url, [], ['timeout' => 10]);\n                }\n            } elseif ($config->rendering == 2) {\n                $ql->use(Chrome::class);\n                $options = ['args' => ['--no-sandbox', '--disable-setuid-sandbox'], 'timeout' => 10000];\n                $ql->chrome(function ($page, $browser) use ($config) {\n                    $page->goto($config->url);\n\n                    for ($i = 1; $i <= $config->pn; $i++) {\n                        // 翻页\n                        $page->evaluate(JsFunction::createWithBody(\"return Promise.resolve(window.scrollTo(0, i*768));\")\n                            ->scope(['i' => $i, 'height' => 768]));\n                        $page->waitFor(500); // 翻页后延迟0.5秒;\n                    }\n\n                    $html = $page->content();\n                    $browser->close();\n                    return $html;\n                }, $options);\n            }\n        } catch (Exception $e){\n            $ql->setHtml('');\n            // http error\n        }\n        $ql->encoding('UTF-8');\n\n        if ($config->remove_head == 2) {\n            $ql->removeHead();\n        }\n\n        return $ql;\n\n    }\n\n    private function _QlInstance(){\n        $ql = QueryList::getInstance();\n        $ql->use([AbsoluteUrl::class, DownloadImage::class, GetTransCoding::class]);\n        $ql->bind('getDataAndRelease', function () {\n            // 获取数据，释放内存\n            $data = $this->getData();\n//            $this->destruct(); // 不销毁ql对象，仅销毁phpQuery Documents占用内存 // TODO: 升级ql后续要改动\n            $this->destructDocuments();\n            return $data->toArray();\n        });\n        $ql->bind('special', function ($config){\n            if (strstr($config->url, 'www.jianshu.com')) {\n                $this->find('.image-container-fill')->remove();\n            }\n            /*\n            if (strstr($config->url, 'mp.weixin.qq.com')) {\n                $this->find('.video_iframe')->map(function($iframe) use ($config){\n                    $iframeSrc = $iframe->attr($config->src);\n                    if (!$iframeSrc){ return ; }\n                    $iframeSrc = preg_replace('/(width|height)=([^&]*)/i', '', $iframeSrc);\n                    $iframe->attr('src', str_replace('&&', '&', $iframeSrc));\n\n                    return $iframe;\n                });\n            }*/\n            return $this;\n        });\n\n        return $ql;\n    }\n\n\n    /**\n     * @param $article\n     * @param $option\n     * @return mixed\n     */\n    protected function insert_article($article, $option){\n\n        if (isset($option['url']))\n        {\n            $info = $this->checkPostLink($option['url']);\n        }else{\n            $info = [];\n        }\n        if (empty($article) | empty($article['title']) | empty($article['content'])) {\n            if (count($info))\n            {\n                $this->wpdb->update($this->table_post, ['status'=>5,'Message'=>\"文章已被删除或者文章格式不正确\"],[\"id\"=>$info[0][\"id\"]]);\n            }\n            return $this->format($article, '内容错误, 出现这个错误是 title 或者 content是空的没获取到。 首先请确保使用debugging的时候是正常的, 可能出现的问题有：目标站有防采集策略、请求频率限制、js跳转拦截策略、或者其他防采集策略, 如果是列表/分页采集、前面一些数据是正常的，后面的出现内容错误，极有可能是命中了访问频率限制策略或js跳转策略。');\n        }\n\n        if (!empty($option['collect_custom_content'])){\n            $stdClass = json_decode($option['collect_custom_content'], true);\n            $stdClass['head'] = htmlspecialchars_decode($stdClass['head'], ENT_QUOTES);\n            $stdClass['foot'] = htmlspecialchars_decode($stdClass['foot'], ENT_QUOTES);\n            $stdClass = str_replace(\n                ['{link}', '{title}', '{title+link}', '{author}', '{name}'],\n                [$article['link'], $article['title'], '<a href=' . $article['link'] . ' target=\"_blank\">' . $article['title'] . '</a>', (isset($article['author']) ? $article['author'] : ''), (isset($article['name']) ? $article['name'] : '')],\n                $stdClass);\n\n            if (!empty($stdClass['head'])) $article['content'] = $stdClass['head'] . $article['content'] ;\n            if (!empty($stdClass['foot'])) $article['content'] = $article['content'] . $stdClass['foot'] ;\n        }\n\n        $data['status'] = 2;\n        $data['option_id'] = $option['id'];\n        $data['cover'] = isset($article['image']) ? $article['image'] : '';\n        $data['link'] = $article['link'];\n        $data['title'] = mb_substr($this->text_keyword_replace($article['title'], $option), 0, 120);\n        $data['content'] = $this->text_keyword_replace($article['content'], $option);\n        $insertKeyword = get_option(FRC_Validation::FRC_VALIDATION_INSERT_KEYWORD);\n        if (!empty($insertKeyword) && json_decode($insertKeyword)->switch == 'open') {\n            $data['content'] = $this->insertKeywords($data['content'], $option);\n        }\n        $data['message'] = 'Success.';\n        $data['created_at'] = current_time('mysql');\n        $data['updated_at'] = current_time('mysql');\n\n        if (empty($info))  $info = $this->checkPostLink($article['link']);\n        if (count($info))\n        {\n            if ($info[0][\"status\"] == 1)\n            {\n                if ($this->wpdb->update($this->table_post, $data,[\"id\"=>$info[0][\"id\"]])){\n                    return $this->format($article, '采集完成');\n                }\n            }else{\n                return $this->format($article, '入库失败、可能此条数据已经在数据库中存在了');\n            }\n        }\n        if ($this->wpdb->insert($this->table_post, $data)){\n            return $this->format($article, '采集完成');\n        }\n    }\n\n\n    /**\n     * @param $txt\n     * @param $option\n     * @return string\n     */\n    protected function insertKeywords($txt, $option){\n        if (empty($option['collect_keywords'])){\n            return $txt;\n        }\n        $keywords = json_decode($option['collect_keywords']);\n        if (empty($keywords)){\n            return $txt;\n        }\n        $items = [];\n        foreach ($keywords as $keyword){\n            for ($i=0; $i<$keyword->count; $i++){\n                if (isset($keyword->link)){\n                    $item = sprintf('<a href=\"%s\">%s</a>', $keyword->link, $keyword->title);\n                } else {\n                    $item = $keyword->title;\n                }\n                array_push($items, $item);\n            }\n        }\n\n        return randomInsertString($txt, $items);\n    }\n\n\n    /**\n     * @param $link\n     * @return array|null|object\n     */\n    protected function checkPostLink($link){\n        return $this->wpdb->get_results(\n            $this->wpdb->prepare(\"select `id`,`status`,`link` from $this->table_post where `link` = %s\", $link),\n            ARRAY_A\n        );\n    }\n\n\n    /**\n     * @param $rules\n     * @return array\n     */\n    private function rulesFormat($rules)\n    {\n        if (empty($rules)){\n            return '';\n        }\n        $resRule = [];\n        collect( explode(\")(\", $rules) )->map(function ($item) use (&$resRule){\n            list($key, $value) = explode(\"%\", $item);\n            list($label, $rule, $filter) = explode(\"|\", $value);\n            $label == 'null' && $label = null;\n            $rule == 'null' && $rule = null;\n            $filter == 'null' && $filter = null;\n            $resRule[$key] = [$label, $rule, $filter];\n        });\n\n        return $resRule;\n    }\n\n    public function response($error, $data = [], $msg = 'ok'){\n        return [\n            '胖鼠采集' => '欢迎使用胖鼠采集调试功能.',\n            'code' => $error,\n            'msg' => $msg,\n            'data' => $data\n        ];\n\n        /*\n        $frc_validation_sponsorship = get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP);\n        if ($frc_validation_sponsorship === 'sponsorship'){\n            return [\n                'code' => $error,\n                '胖鼠' => FRC_Validation::FRC_HINT_D,\n                'msg' => $msg,\n                'data' => $data\n            ];\n        }\n\n        if (time() - get_option(FRC_Validation::FRC_INSERT_TIME) < 86400){\n            return [\n                'code' => $error,\n                'msg' => $msg,\n                'data' => $data\n            ];\n        }\n\n        $frc_validation_debug_count = get_option(FRC_Validation::FRC_VALIDATION_DEBUG_COUNT, '0');\n        if ($frc_validation_debug_count === '0'){\n            return array_merge(FRC_Validation::FRC_DEBUG_INFO_PROMPT, [\n                'code' => $error,\n                'msg' => $msg\n            ]);\n        }\n\n        $remaining = $frc_validation_debug_count-1;\n        update_option(FRC_Validation::FRC_VALIDATION_DEBUG_COUNT, $remaining);\n        return [\n            'code' => $error,\n            '胖鼠' => sprintf(FRC_Validation::FRC_HINT_E, $remaining),\n            'msg' => $msg,\n            'data' => $data\n        ];*/\n    }\n\n\n    /**\n     * @param $article\n     * @param string $msg\n     * @return mixed\n     */\n    protected function format($article, $msg = ''){\n        $article['message'] = $msg;\n        $article['content'] = !empty($article['content']) ? mb_substr($article['content'], 0, 100).'.....' : '';\n\n        return $article;\n    }\n\n\n    /**\n     * @param $time\n     * @return bool\n     */\n    private function checkWechatHistoryTimeLimit($time)\n    {\n        $toDay = get_option(\"fat_rat_collect_wechat_history_time_\" . date(\"Y-m-d\"));\n        if (!$toDay)\n        {\n            $toDayTime = $time;\n        }else{\n            $toDayTime = $toDay + $time;\n        }\n        if ($toDayTime > 500) return false;\n        update_option(\"fat_rat_collect_wechat_history_time_\" . date(\"Y-m-d\"), $toDayTime);\n        return true;\n    }\n}\n\nfunction frc_spider()\n{\n    if (!frc_mysql_upgrade()){\n        return ;\n    }\n    frc_front_loading();\n    $frc_options = new FRC_Options();\n    $options = collect($frc_options->options())->reverse()->groupBy('collect_type');\n    // TODO:首页拆分。优化速度。\n    ?>\n\n    <div class=\"wrap\">\n        <h1 class=\"frc-plugin-name\">\n            <?php esc_html_e('胖鼠采集', 'Fat Rat Collect') ?>\n            <?php if (!empty(get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP))) { ?>\n                <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png') ?>\" />\n            <?php } ?>\n            <img width=\"80\" class=\"float-end\" src=\"<?php frc_image('fat-rat-256x256.png') ?>\">\n        </h1>\n        <p></p>\n        <span style=\"font-size: 14px\">\n        <?php\n        if (array_rand([1, 2], 1) === 1) {\n            esc_html_e('胖鼠采集, WordPress最好用的开源采集小工具');\n        } else {\n            esc_html_e('胖鼠采集, WordPress优秀开源采集插件');\n        }\n        ?></span>\n        <p></p>\n        <div><p style=\"color: #0000cc\"><?php _e((new FRC_Validation())->announcement('notice-home')); ?></p></div>\n\t    <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n        <div class=\"progress progress-striped active\">\n            <div id=\"bootstrop-progress-bar\" class=\"progress-bar progress-bar-success progress-bar-striped spider-progress-bar\" role=\"progressbar\"\n                 aria-valuenow=\"60\" aria-valuemin=\"0\" aria-valuemax=\"100\"\n                 style=\"width: 0%;\">\n            </div>\n        </div>\n        <p></p>\n<!--        <ul class=\"nav nav-tabs\">-->\n<!--            <li class=\"active\"><a href=\"#single_wx\" data-toggle=\"tab\">微信爬虫</a></li>-->\n<!--            <li><a href=\"#single_js\" data-toggle=\"tab\">简书爬虫</a></li>-->\n<!--            <li><a href=\"#single_zh\" data-toggle=\"tab\">知乎采集</a></li>-->\n<!--            <li><a href=\"#list\" data-toggle=\"tab\">列表采集</a></li>-->\n<!--            <li><a href=\"#historypage\" data-toggle=\"tab\">列表分页采集</a></li>-->\n<!--            <li><a href=\"#details\" data-toggle=\"tab\">详情采集</a></li>-->\n<!--            --><?php //if (get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT)){ ?>\n<!--            <li><a href=\"#all\" data-toggle=\"tab\">全站采集</a></li>-->\n<!--            --><?php //} ?>\n<!--            <li><a href=\"#todolist\" data-toggle=\"tab\">Todo & 胖鼠</a></li>-->\n<!--        </ul>-->\n        <nav>\n            <div class=\"nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\n                <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#single_wx\" type=\"button\">微信爬虫</button>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#single_js\" type=\"button\">简书爬虫</button>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#single_zh\" type=\"button\">知乎采集</button>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#list\" type=\"button\">列表采集</button>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#historypage\" type=\"button\">列表分页采集</button>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#details\" type=\"button\">详情采集</button>\n                <?php if (get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT)){ ?>\n                    <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#all\" type=\"button\">全站采集</button>\n                <?php } ?>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#wechat_history\" type=\"button\">微信公众号历史文章采集<img width=\"25\" src=\"<?php frc_image('new.png') ?>\" /></button>\n                <button class=\"nav-link\" data-bs-toggle=\"tab\" data-bs-target=\"#todolist\" type=\"button\">Todo & 胖鼠</button>\n            </div>\n        </nav>\n        <div class=\"tab-content spider-tab-content\">\n            <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n            <!--微信爬虫-->\n            <div class=\"tab-pane fade show active\" id=\"single_wx\">\n                <table class=\"form-table\">\n                    <tr>\n                        <th>微信文章地址</th>\n                        <td>\n                            <textarea name=\"collect_wx_urls\" cols=\"80\" rows=\"14\" placeholder=\"把微信公众号文章链接直接粘贴进来. 点击采集即可. 推荐使用短的Url,点击复制的那种\n多篇文章使用回车区分, 一行一个.\"></textarea>\n                            <p>小提示: 如需要内容过滤需求 如删除: 第一张图片 or 第二个p标签 or 倒数第三张图片 等需求 请使用<a href=\"https://www.fatrat.cn/docs/v2/content-filtering\" target=\"_blank\">内容过滤</a>功能</p>\n                            <p>例: -img:gt(-4) 过滤文章底部倒数3张图片! -img:eq(1) 只过滤文章正文第2张图片 (程序从0开始)</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th colspan=\"2\">\n                            <button type=\"button\" class=\"btn btn-primary wx-spider-run-button\" id=\"liveToastBtn\">采集</button>\n                        </th>\n                    </tr>\n                </table>\n            </div>\n            <!--简书爬虫-->\n            <div class=\"tab-pane fade\" id=\"single_js\">\n                <table class=\"form-table\">\n                    <tr>\n                        <th>简书文章地址</th>\n                        <td>\n                            <textarea name=\"collect_js_urls\" cols=\"80\" rows=\"14\" placeholder=\"多篇文章使用回车区分, 一行一个\"></textarea>\n                            <p>Tips: 简书默认规则过滤了a标签, 一定要了解a与-a的区别哦、 你们可以在配置中心查看胖鼠写的配置</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th colspan=\"2\">\n                            <button type=\"button\" class=\"btn btn-primary js-spider-run-button\" id=\"liveToastBtn\">采集</button>\n                        </th>\n                    </tr>\n                </table>\n            </div>\n            <!--知乎爬虫-->\n            <div class=\"tab-pane fade\" id=\"single_zh\">\n                <table class=\"form-table\">\n                    <tr>\n                        <th>知乎(问答)地址</th>\n                        <td>\n                            <textarea name=\"collect_zh_urls\" cols=\"80\" rows=\"14\" placeholder=\"多篇文章使用回车区分, 一行一个\"></textarea>\n                            <p>Tips: 此规则是采集知乎问答页面, 不是知乎文章详情页</p>\n                            <p>可使用F12调试模式、查看采集结果哦</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th colspan=\"2\">\n                            <button type=\"button\" class=\"btn btn-primary zh-spider-run-button\" id=\"liveToastBtn\">采集</button>\n                        </th>\n                    </tr>\n                </table>\n            </div>\n            <!--列表爬虫-->\n            <div class=\"tab-pane fade spider-tab-content\" id=\"list\">\n                <?php\n                if (!isset($options['list'])) {\n                    _e('<p></p>');\n                    _e(\"<h4><a href='\". admin_url('admin.php?page=frc-options') .\"'>亲爱的皮皮虾: 目前没有任何一个列表配置。皮皮虾我们走 </a></h4>\");\n                } else {\n                ?>\n                <ul class=\"list-group\">\n                    <p></p>\n                    <a disabled class=\"list-group-item active\">\n                        <h5 class=\"list-group-item-heading\">\n                            列表爬虫(点击采集)\n                        </h5>\n                    </a>\n                    <p></p>\n                    <?php\n                    foreach ($options['list'] as $option) {\n                        _e(\"<a href='javascript:;' data-id='{$option['id']}' class='list-spider-run-button list-group-item'>{$option['collect_name']}</a>\");\n                    }\n                    ?>\n                    <!-- bootstrap进度条 -->\n                    <p></p>\n                    <?php _e((new FRC_Validation())->getAppreciatesHtml(7)); ?>\n                </ul>\n                <?php } ?>\n            </div>\n            <!--分页爬虫-->\n            <div class=\"tab-pane fade\" id=\"historypage\">\n                <p class=\"p-tips-style\"><?php esc_html_e(FRC_ApiError::FRC_TIPS[array_rand(FRC_ApiError::FRC_TIPS, 1)]); ?></p>\n                <?php\n                if (!isset($options['list'])) {\n                    _e('<p></p>');\n                    _e(\"<h4><a href='\". admin_url('admin.php?page=frc-options') .\"'>亲爱的毛毛虫: 目前没有任何一个分页配置。毛毛虫我们走 </a></h4>\");\n                } else {\n                ?>\n                <table class=\"form-table\">\n                    <tr>\n                        <th>选择页面的规则配置</th>\n                        <td>\n                            <?php\n                            $option_list = $options['list'];\n                            $string = '<select class=\"form-select\" name=\"collect_history_relus\"><option value=\"0\">请选择一个配置</option>';\n                            foreach ($option_list as $option) {\n                                $string .= '<option value=\"'.$option['id'].'\">'.$option['collect_name'].'</option>';\n                            }\n                            $string .= '</select>';\n                            _e($string);\n                            ?>\n                            <p>配置创建在 新建配置->配置类型=列表</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>采集页码/翻页</th>\n                        <td>\n                            <input name=\"collect_history_page_number\" size=\"82\" placeholder=\"2-10\" />\n                            <p>页码用 - 隔开 例: 2-10 采集2->10页</p>\n                            <?php if (get_option(FRC_Validation::FRC_VALIDATION_RENDERING)){ ?>\n                                <p>动态渲染页面是向下翻页几次 例: 3 向下翻页三次, 翻页高度768px</p>\n                            <?php } ?>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th colspan=\"2\">\n                            <button type=\"button\" class=\"btn btn-primary history-page-spider-run-button\" id=\"liveToastBtn\">采集</button>\n                        </th>\n                    </tr>\n                    <tr>\n                        <td colspan=\"2\"><?php _e((new FRC_Validation())->getAppreciatesHtml(7)); ?></td>\n                    </tr>\n                </table>\n                <?php } ?>\n            </div>\n            <!--详情爬虫-->\n            <div class=\"tab-pane fade\" id=\"details\">\n                <?php\n                if (!isset($options['single'])) {\n                    _e('<p></p>');\n                    _e(\"<h4><a href='\". admin_url('admin.php?page=frc-options') .\"'>亲爱的皮皮: 目前没有任何一个详情配置。胖鼠我们走 </a></h4>\");\n                } else {\n                ?>\n                <table class=\"form-table\">\n                    <tr>\n                        <th>详情地址</th>\n                        <td>\n                            <textarea name=\"collect_details_urls\" cols=\"80\" rows=\"14\" placeholder=\"输入目标url, 这里使用你配置的详情配置, 胖鼠采集 WordPress优秀开源采集插件.\"></textarea>\n                            <p></p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>详情配套配置</th>\n                        <td>\n                            <?php\n                            $string = '<select name=\"collect_details_relus\"><option value=\"0\">请选择</option>';\n                            foreach ($options['single'] as $option) {\n                                if (in_array($option['collect_name'], FRC_ApiError::BUTTON_DISABLED)){\n                                    $string .= '<option disabled value=\"'.$option['id'].'\">'.$option['collect_name'].'</option>';\n                                } else {\n                                    $string .= '<option value=\"'.$option['id'].'\">'.$option['collect_name'].'</option>';\n                                }\n                            }\n                            $string .= '</select>';\n                            _e($string);\n                            ?>\n                            <p>配置创建在 新建配置->配置类型=详情</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th colspan=\"2\">\n                            <button type=\"button\" class=\"btn btn-primary details-spider-run-button\" id=\"liveToastBtn\">采集</button>\n                        </th>\n                    </tr>\n                    <tr>\n                        <td colspan=\"2\"><?php _e((new FRC_Validation())->getAppreciatesHtml(7)); ?></td>\n                    </tr>\n                </table>\n                <?php } ?>\n            </div>\n            <!--全站采集-->\n            <div class=\"tab-pane fade spider-tab-content\" id=\"all\">\n                <?php\n                if (!isset($options['all'])) {\n                    _e('<p></p>');\n                    _e(\"<h4><a href='\". admin_url('admin.php?page=frc-options') .\"'>亲爱的胖球: 目前没有任何一个全站采集配置。兔子我们走 </a></h4>\");\n                } else {\n                    ?>\n                    <ul class=\"list-group\">\n                        <p></p>\n                        <a disabled class=\"list-group-item active\">\n                            <h5 class=\"list-group-item-heading\">\n                                全站采集\n                            </h5>\n                        </a>\n                        <p></p>\n                        <?php\n                        foreach ($options['all'] as $option) {\n                            _e(\"<a href='javascript:;' data-id='{$option['id']}' class='all-spider-run-button list-group-item'>{$option['collect_name']}</a>\");\n                        }\n                        ?>\n                        <p></p>\n                    </ul>\n                <?php } ?>\n            </div>\n            <!--微信公众号历史文章-->\n            <div class=\"tab-pane fade \" id=\"wechat_history\">\n                <table class=\"form-table\">\n                    <tr>\n                        <th>使用文档：</th>\n                        <td>\n                            <p><a target=\"_blank\" href=\"https://www.fatrat.cn/docs/v2/wechat-history-collection\">点击阅读</a></p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>微信公众平台cookie：</th>\n                        <td>\n                            <textarea name=\"collect_wx_app_cookie\" cols=\"80\" rows=\"14\" placeholder=\"请输入在微信公众平台获取到的cookie\"></textarea>\n                            <p style=\"color: red;\">此处粘贴F12控制台网络请求过滤 <e style=\"background-color: #ffffaa;color: #000\">https://mp.weixin.qq.com/cgi-bin/appmsgpublish</e> 获取此次请求的请求头中的cookie</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>微信公众平台token：</th>\n                        <td>\n                            <input name=\"collect_wx_app_token\" size=\"40\" placeholder=\"请输入在微信公众平台获取到的token\">\n                            <p style=\"color: red;\">打开微信公众平台后，F12打开控制台console执行 <e style=\"background-color: #ffffaa;color: #000\">console.log(  new URLSearchParams(window.location.search).get(\"token\"))</e> 后粘贴结果</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>微信公众号名称：</th>\n                        <td>\n                            <input name=\"collect_wechat_app_name\" size=\"40\" placeholder=\"微信公众号全称\"/>\n                            <p style=\"color: red;\">小提示: 请确认全称无误</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>起始页数（从哪页开始采）：</th>\n                        <td>\n                            <input name=\"collect_wechat_app_start_number\" size=\"40\" placeholder=\"起始页数\" value=\"1\"/>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th>采集页数（采集多少页）：</th>\n                        <td>\n                            <input name=\"collect_wechat_app_number\" size=\"40\" placeholder=\"采集页数\" value=\"1\"/>\n                            <p style=\"color: red;\">小提示:</p>\n                            <p style=\"color: red;\">      一页为20次文章发布（每次文章发布包含多次文章）</p>\n                            <p style=\"color: red;\">      目前单次最多可采集30页，单日最大可采集500页</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th style=\"color: red;\">声明:</th>\n                        <td>\n                            <p style=\"color: red;\">       为避免公众号被封禁，此功能已进行频率控制，请避免频繁使用。</p>\n                            <p style=\"color: red;\">       如需大批量采集，建议有条件的用户准备多个微信公众号参数并进行轮换使用，以规避频繁调用风险。</p>\n                            <p style=\"color: red;\">       其他选择是申请几个空白公众号专用于接口调用（无需备案或其他花费）。</p>\n                            <p style=\"color: red;\">       功能用于学习交流，对于因不当使用此功能而导致的账号封禁，请自行负责</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <th colspan=\"2\">\n                            <button type=\"button\" class=\"btn btn-primary wx-history-spider-run-button\" id=\"liveToastBtn\">采集</button>\n                        </th>\n                    </tr>\n                </table>\n            </div>\n            <!--胖鼠 && Todo-->\n            <div class=\"tab-pane fade\" id=\"todolist\">\n                <p></p>\n                <p class=\"p-tips-style\"><?php esc_html_e(FRC_ApiError::FRC_TIPS[array_rand(FRC_ApiError::FRC_TIPS, 1)]); ?></p>\n                <div class=\"todo-and-author-class\">\n                    <div align=\"right\" style=\"margin-top: 0px; float: right;\">\n                        <img width=\"300\" src=\"<?php frc_image('fat-rat-appreciates.jpeg'); ?>\" />\n                    </div>\n                    <h5>鼠言鼠语:</h5>\n                    <ul style=\"\">\n                        <?php if (get_option(FRC_Validation::FRC_INSERT_TIME) != '') { ?>\n                            <li style=\"color: #9b51e0\">鼠友, 我们第一次相遇是在 <?php esc_html_e(date('Y年m月d日 H:i', get_option(FRC_Validation::FRC_INSERT_TIME))) ?> 在此留影, 以示纪念. </li>\n                        <?php } ?>\n                        <li><a href=\"https://www.fatrat.cn\" target=\"_blank\">胖鼠采集</a>是github开源作品, 有问题欢迎大家在<a href=\"https://github.com/KitePig/FatRat-Collect\" target=\"_blank\">github</a>的issues提问.</li>\n                        <li>胖鼠支持有能力鼠友2次开发胖鼠采集开源使用, 鼠友不可直接Copy && Rename</a></li>\n                        <li>胖鼠采集, 最重要的应该是新建一个规则并上手使用, 我觉得通过视频教程、文字教程的学习后, 20分钟就能就能搞定.</li>\n                        <li>新建采集规则, 有默认的配置. 可一键导入, 无需等待, 即刻使用. 鼠友照葫芦画瓢即可.</li>\n                        <li>欢迎鼠友给胖鼠采集<a href=\"https://www.fatrat.cn/bounty\" target=\"_blank\"> 赞赏</a>, 同时也可以给胖鼠采集插件<a href=\"https://wordpress.org/support/plugin/fat-rat-collect/reviews\" target=\"_blank\">五星好评</a>, 这也算对胖鼠采集无声的支持.</li>\n                        <li>胖鼠采集: 1群:454049736(已满) 2群:846069514(已满) 3群/4群(微信群): waxx-xxswnb 加胖鼠好友,或扫描下方二维码</li>\n                        <li>胖鼠采集为开源学习交流, 严禁有任何违反国家法律的行为.</li>\n                        <li>胖鼠采集 20181230</li>\n                        <li><img width=\"200\" src=\"<?php frc_image('fat-rat-pswx.png'); ?>\" /></li>\n                        <li><img src=\"<?php frc_image('fat-rat-128x128.png'); ?>\" /></li>\n                    </ul>\n                    <hr />\n                    <?php require_once(plugin_dir_path(__DIR__) . 'views/todo.html'); ?>\n                </div>\n            </div>\n        </div>\n    </div>\n    <?php\n}\n\nfunction frc_mysql_upgrade(){\n    if (get_plugin_data(plugin_dir_path(__DIR__).'fatratcollect.php')['Version'] > '2.0.0'){\n        //2.0以上版本不需要数据库升级\n        return true;\n    }\n    $option = get_option('frc_mysql_upgrade');\n    if ($option == 'upgrade complete'){\n        return true;\n    }\n    $last_id = get_option('frc_mysql_upgrade_progress', 0);\n    ?>\n        <h1>鼠友你好吖, 欢迎来到胖鼠采集v2.0的新世界</h1>\n        <h1>此次大版本更新, 耗时无数夜晚, 重写了胖鼠采集底层</h1>\n        <h1>接下来请进行数据库迁移升级, 如遇到问题请到群内寻找帮助</h1>\n        <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n        <input type=\"hidden\" hidden id=\"success_redirect_url\" value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-spider')); ?>\">\n\n        <hr />\n\n        <?php\n            if ($option == '1'){\n                _e(sprintf('<button class=\"frc_mysql_upgrade btn btn-danger btn-lg\" data-value=\"1\">(①)点我迁移升级采集配置</button>'));\n            } elseif ($option == '2') {\n                _e(sprintf('<button class=\"frc_mysql_upgrade btn btn-danger btn-lg\" data-value=\"2\">(②)点我迁移升级采集数据表</button>'));\n                _e(sprintf('<h3>大数据量用户会进行分段数据迁移,每次迁移500条,目前数据库迁移进度%s</h3>', $last_id));\n            } else {\n                update_option('frc_mysql_upgrade', 'upgrade complete');\n                _e('<h1>升级已结束</h1>');\n            }\n        ?>\n\n        <h3>过程可能过长, 请耐心等待.</h3>\n    <?php\n\n    return false;\n}\n\nfunction frc_front_loading(){\n    array_rand(range(1,3)) == 0 && (new FRC_Validation())->notice();\n    (new FRC_Validation())->report_permissions();\n}\n"
  },
  {
    "path": "includes/fatrat-validation.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * 如果你觉得这个项目还不错.可以去Github上 Star 关注我.\n * 您可使用胖鼠采集自行二次开发满足您的个性化需求.\n * 请不要Copy, Rename. OR 修改源代码进行售卖获利.\n * Github: https://github.com/fbtopcn/fatratcollect\n * @Author: fbtopcn\n * @CreateTime: 2020年4月1日\n */\n\nclass FRC_Validation {\n\n    private $url = 'https://www.fatrat.cn';\n\n    const FRC_API_CODE = '20';\n    const FRC_INSERT_TIME = 'frc_install_time';\n    const FRC_VALIDATION_NOTICE = 'frc_validation_notice';\n    const FRC_VALIDATION_FEATURED_PICTURE = 'frc_validation_featured_picture';\n    const FRC_VALIDATION_DYNAMIC_FIELDS = 'frc_validation_dynamic_fields';\n    const FRC_VALIDATION_AUTOMATIC_SAVE_PIC = 'frc_validation_automatic_save_pic';\n    const FRC_VALIDATION_RELEASE_CONTROL = 'frc_validation_release_control';\n    const FRC_VALIDATION_INSERT_KEYWORD = 'frc_validation_insert_keyword';\n\n    const FRC_VALIDATION_WECHAT_HISTORY = 'frc_validation_wechat_history';\n\n    const FRC_VALIDATION_AUTO_TAGS = 'frc_validation_auto_tags';\n    const FRC_VALIDATION_INNER_CHAIN = 'frc_validation_inner_chain';\n    const FRC_VALIDATION_ALL_COLLECT = 'frc_validation_all_collect';\n    const FRC_VALIDATION_RENDERING = 'frc_validation_rendering';\n    const FRC_VALIDATION_SPONSORSHIP = 'frc_validation_sponsorship';\n    const FRC_VALIDATION_DEBUG_RECHARGE = 'frc_validation_debug_recharge';\n    const FRC_API_CODE_PERMISSIONS = '44';\n    const FRC_VALIDATION_ABILITY_MAP = [\n        'auto-tags' => [self::FRC_VALIDATION_AUTO_TAGS, '2'],\n        'inner-chain' => [self::FRC_VALIDATION_INNER_CHAIN, '2'],\n        'featured-picture' => [self::FRC_VALIDATION_FEATURED_PICTURE, '2'],\n        'dynamic-fields' => [self::FRC_VALIDATION_DYNAMIC_FIELDS, '2'],\n        'all-collect' => [self::FRC_VALIDATION_ALL_COLLECT, '1'],\n        'rendering' => [self::FRC_VALIDATION_RENDERING, '1'],\n        'automatic-save-pic' => [self::FRC_VALIDATION_AUTOMATIC_SAVE_PIC, '1'],\n        'sponsorship' => [self::FRC_VALIDATION_SPONSORSHIP, 'sponsorship'],\n        'release-control' => [self::FRC_VALIDATION_RELEASE_CONTROL, '1'],\n        'insert-keyword' => [self::FRC_VALIDATION_INSERT_KEYWORD, '2'],\n        'wechat-history' => [self::FRC_VALIDATION_WECHAT_HISTORY, '1'],\n    ];\n    const FRC_HINT_A = '感谢鼠友%s的赞助, %s为您充值%s次, 您剩余 %s 次';\n    const FRC_HINT_B = '咣咣咣, 人品大爆发, 感谢鼠友%s为您带来翻倍奖励, %s本次为您充值%s次, 您剩余 %s 次';\n    const FRC_HINT_C = '赞助鼠半小时只能为您支持一次哦.';\n    const FRC_HINT_D = '鼠友你好, 感谢您的赞助支持, 胖鼠采集因您更美好.';\n    const FRC_HINT_E = 'debugging功能剩余次数(%s)次';\n    const FRC_HINT_F = '分页采集占用系统资源, 单次采集页数不可大于3页, 赞助鼠友可以无限制哦';\n    const FRC_HINT_G = '操作状态成功le.';\n    const FRC_HINT_H = '您的debugging剩余次数太多了, 无需充值.';\n    const FRC_HINT_J = '插件的发展需要您的支持, 感谢赞助.';\n    const FRC_HINT_K = '网络连接失败, 请求超时, 如异常持续, 请联系胖鼠排查原因!';\n    const FRC_HINT_L = '保存完成, 已设置默认发布选项, 如需自定义发布选项 请赞助支持, 开源不易感谢支持.';\n    const FRC_HINT_Z = '非赞助鼠友最多可创建5个配置哦, 开源不易感谢支持';\n    const FRC_HINT_M = '当前登陆的WordPress账号无操作权限，请使用后台管理员账号进行操作.';\n\n    private $shutdownJson;\n    private $openJson;\n\n    public function __construct()\n    {\n        $this->shutdownJson = json_encode(['switch' => 'shutdown', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql')]);\n        $this->openJson = json_encode(['switch' => 'open', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql')]);\n    }\n\n\n    public function validation_function_switch(){\n        if ($this->update_switch(self::FRC_VALIDATION_ABILITY_MAP[frc_sanitize_text('switch_action')][0])){\n            return ['code' => FRC_ApiError::SUCCESS, 'msg' => self::FRC_HINT_G];\n        } else {\n            return ['code' => FRC_ApiError::FAIL, 'msg' => 'Fail.'];\n        }\n    }\n\n\n    public function validation_activation(){\n        $action = frc_sanitize_text('activation_action');\n        $data = $this->validation_request('/validation', ['action' => $action], 5);\n        if (isset($data)) {\n            $data = json_decode($data);\n            if (!$this->checkAccessToken($data)){\n                return ['code' => FRC_ApiError::ERR_TOKEN, 'msg' => FRC_ApiError::msg(FRC_ApiError::ERR_TOKEN)];\n            }\n            if ($data->code == self::FRC_API_CODE) {\n                $config = self::FRC_VALIDATION_ABILITY_MAP[$action];\n                switch ($config[1]){\n                    case '1':\n                        $config[1] = $this->openJson;\n                        break;\n                    case '2':\n                        $config[1] = $this->shutdownJson;\n                        break;\n                }\n\n                if ($data->data)\n                {\n                    $config[1] = collect(json_decode($config[1],true))->merge($data->data)->toJson();\n                }\n\t\t\t\t$result = add_option($config[0], $config[1]);\n\t\t\t\tif (!$result){\n\t\t\t\t\t$result = update_option($config[0], $config[1]);\n\t\t\t\t}\n                return ['code' => FRC_ApiError::SUCCESS, 'msg' => $data->msg, 'data' => $result];\n            } else {\n                return ['code' => FRC_ApiError::NO_PERMISSION, 'msg' => isset($data->msg) ? $data->msg : '验证失败.'];\n            }\n        } else {\n            return ['code' => FRC_ApiError::CHECK_SERVER_FAIL, 'msg' => '网络错误, 请重试. '];\n        }\n    }\n\n\n    protected function update_switch($action){\n        $result = get_option($action);\n        if (empty($result)){\n            return false;\n        }\n        $option = json_decode($result, true);\n        $option['switch'] = ($option['switch'] == 'open') ? 'shutdown' : 'open';\n        return update_option($action, json_encode($option));\n    }\n\n    public function validation_correction(){\n        foreach (self::FRC_VALIDATION_ABILITY_MAP as $item){\n            delete_option($item[0]);\n        }\n        delete_option('frc_cron_release');\n        delete_option('frc_cron_spider');\n    }\n\n    public function notice(){\n        try{\n            $notice = $this->validation_request_static('/static/notice.json');\n            update_option(self::FRC_VALIDATION_NOTICE, $notice);\n        } catch (\\GuzzleHttp\\Exception\\RequestException $e){\n            delete_option(self::FRC_VALIDATION_NOTICE);\n        }\n    }\n\n    public function announcement($location = 'notice-home'){\n        try{\n            $notice = get_option(self::FRC_VALIDATION_NOTICE);\n            $notice = json_decode($notice);\n            if (isset($notice->$location)){\n                if ($notice->$location->type == 'link'){\n                    return sprintf($notice->$location->string, '<a href=\"'.$notice->$location->link.'\" target=\"_blank\">'.$notice->$location->title.'</a>');\n                } else {\n                    return $notice->$location->string;\n                }\n            }\n        } catch (\\GuzzleHttp\\Exception\\RequestException $e){\n            return '';\n        }\n\n        return '';\n    }\n\n    public function report_permissions() {\n        $report_time = get_option('frc_report_permissions_time', time()-10);\n        if ( time() < $report_time ){\n            return ;\n        }\n        $permissions = array('power' => [], 'other' => []);\n        collect(self::FRC_VALIDATION_ABILITY_MAP)->map(function ($permission, $key) use (&$permissions){\n            $permissions['power'][$key] = (get_option($permission[0], null)? 'open' : 'null');\n        });\n        $data = $this->validation_request('/validation/report', ['permissions' => serialize($permissions)], 1);\n        if (isset($data)) {\n            $data = json_decode($data);\n            if ($data->code == self::FRC_API_CODE && $this->checkAccessToken($data)) {\n                update_option('frc_report_permissions_time', strtotime('+10day'));\n                return;\n            } elseif ($data->code == self::FRC_API_CODE_PERMISSIONS && $this->checkAccessToken($data)) {\n                foreach ($data->data->power as $permission => $val){\n                    if ($val === 'abnormal'){\n                        delete_option(self::FRC_VALIDATION_ABILITY_MAP[$permission][0]);\n                    }\n                }\n                update_option('frc_report_permissions_time', strtotime('+5hours'));\n            } else {\n                update_option('frc_report_permissions_time', strtotime('+3day'));\n            }\n        }\n        return ;\n    }\n\n    public function getAppreciatesHtml($count = 5){\n        $html = '<ul class=\"frc-appreciate-class\"><li>感谢赞助鼠: </li>';\n        foreach ($this->appreciates($count) as $appreciate) {\n            if (isset($appreciate->site) && isset($appreciate->site_url)){\n                $html .= sprintf('<li>%s: (<a href=\"%s\" target=\"_blank\">%s</a>)</li>', $appreciate->people, $appreciate->site_url, $appreciate->site);\n            } else {\n                $html .= sprintf('<li>%s</li>', $appreciate->people);\n            }\n        }\n\n        $html .= '</ul>';\n\n        return $html;\n\n    }\n\n    public function appreciates($count = null){\n        $notice = get_option(self::FRC_VALIDATION_NOTICE);\n        $notice = json_decode($notice);\n        if (isset($notice->appreciates)){\n            if ($count === null){\n                return $notice->appreciates;\n            }\n            shuffle($notice->appreciates);\n            return array_slice($notice->appreciates, 0, $count);\n        }\n        return [];\n    }\n\n    private function checkAccessToken($data){\n        return true;\n        // return ($data->token === md5(parse_url($this->url)['host'].date('Y-m-d ?:i').$data->code.$data->msg));\n    }\n\n    private function getAccessToken(){\n        return md5(date('Y-m-d ?:i').site_url());\n    }\n\n    private function validation_request_static($path, $timeout = 1){\n        return (new \\GuzzleHttp\\Client())->request('get', $this->url.$path, ['verify' => false, 'connect_timeout' => $timeout])->getBody()->getContents();\n    }\n\n    private function validation_request($uri, $query = [], $timeout = 1){\n\n        try{\n            $query['host'] = site_url();\n            $query['token'] = $this->getAccessToken();\n            $query['version'] = get_option('frc_db_version');\n            $http = (new \\GuzzleHttp\\Client())->request('post', $this->url.'/api'.$uri, ['verify' => false, 'connect_timeout' => $timeout, 'form_params' => $query]);\n            update_option('fat_rat_collect_api_code', $http->getStatusCode());\n            return $http->getBody()->getContents();\n        } catch (Exception $e) {\n            update_option('fat_rat_collect_api_code', $e->getCode());\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "public/css/bootstrap.css",
    "content": "@charset \"UTF-8\";\n/*!\n * Bootstrap v5.0.2 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n:root {\n  --bs-blue: #0d6efd;\n  --bs-indigo: #6610f2;\n  --bs-purple: #6f42c1;\n  --bs-pink: #d63384;\n  --bs-red: #dc3545;\n  --bs-orange: #fd7e14;\n  --bs-yellow: #ffc107;\n  --bs-green: #198754;\n  --bs-teal: #20c997;\n  --bs-cyan: #0dcaf0;\n  --bs-white: #fff;\n  --bs-gray: #6c757d;\n  --bs-gray-dark: #343a40;\n  --bs-primary: #0d6efd;\n  --bs-secondary: #6c757d;\n  --bs-success: #198754;\n  --bs-info: #0dcaf0;\n  --bs-warning: #ffc107;\n  --bs-danger: #dc3545;\n  --bs-light: #f8f9fa;\n  --bs-dark: #212529;\n  --bs-font-sans-serif: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", \"Liberation Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n  --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n  --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));\n}\n\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n  :root {\n    scroll-behavior: smooth;\n  }\n}\n\nbody {\n  margin: 0;\n  font-family: var(--bs-font-sans-serif);\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  background-color: #fff;\n  -webkit-text-size-adjust: 100%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nhr {\n  margin: 1rem 0;\n  color: inherit;\n  background-color: currentColor;\n  border: 0;\n  opacity: 0.25;\n}\n\nhr:not([size]) {\n  height: 1px;\n}\n\nh6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n  font-weight: 500;\n  line-height: 1.2;\n}\n\nh1, .h1 {\n  font-size: calc(1.375rem + 1.5vw);\n}\n@media (min-width: 1200px) {\n  h1, .h1 {\n    font-size: 2.5rem;\n  }\n}\n\nh2, .h2 {\n  font-size: calc(1.325rem + 0.9vw);\n}\n@media (min-width: 1200px) {\n  h2, .h2 {\n    font-size: 2rem;\n  }\n}\n\nh3, .h3 {\n  font-size: calc(1.3rem + 0.6vw);\n}\n@media (min-width: 1200px) {\n  h3, .h3 {\n    font-size: 1.75rem;\n  }\n}\n\nh4, .h4 {\n  font-size: calc(1.275rem + 0.3vw);\n}\n@media (min-width: 1200px) {\n  h4, .h4 {\n    font-size: 1.5rem;\n  }\n}\n\nh5, .h5 {\n  font-size: 1.25rem;\n}\n\nh6, .h6 {\n  font-size: 1rem;\n}\n\np {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-bs-original-title] {\n  -webkit-text-decoration: underline dotted;\n  text-decoration: underline dotted;\n  cursor: help;\n  -webkit-text-decoration-skip-ink: none;\n  text-decoration-skip-ink: none;\n}\n\naddress {\n  margin-bottom: 1rem;\n  font-style: normal;\n  line-height: inherit;\n}\n\nol,\nul {\n  padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n  margin-bottom: 0;\n}\n\ndt {\n  font-weight: 700;\n}\n\ndd {\n  margin-bottom: 0.5rem;\n  margin-left: 0;\n}\n\nblockquote {\n  margin: 0 0 1rem;\n}\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\nsmall, .small {\n  font-size: 0.875em;\n}\n\nmark, .mark {\n  padding: 0.2em;\n  background-color: #fcf8e3;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 0.75em;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nsup {\n  top: -0.5em;\n}\n\na {\n  color: #0d6efd;\n  text-decoration: underline;\n}\na:hover {\n  color: #0a58ca;\n}\n\na:not([href]):not([class]), a:not([href]):not([class]):hover {\n  color: inherit;\n  text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: var(--bs-font-monospace);\n  font-size: 1em;\n  direction: ltr /* rtl:ignore */;\n  unicode-bidi: bidi-override;\n}\n\npre {\n  display: block;\n  margin-top: 0;\n  margin-bottom: 1rem;\n  overflow: auto;\n  font-size: 0.875em;\n}\npre code {\n  font-size: inherit;\n  color: inherit;\n  word-break: normal;\n}\n\ncode {\n  font-size: 0.875em;\n  color: #d63384;\n  word-wrap: break-word;\n}\na > code {\n  color: inherit;\n}\n\nkbd {\n  padding: 0.2rem 0.4rem;\n  font-size: 0.875em;\n  color: #fff;\n  background-color: #212529;\n  border-radius: 0.2rem;\n}\nkbd kbd {\n  padding: 0;\n  font-size: 1em;\n  font-weight: 700;\n}\n\nfigure {\n  margin: 0 0 1rem;\n}\n\nimg,\nsvg {\n  vertical-align: middle;\n}\n\ntable {\n  caption-side: bottom;\n  border-collapse: collapse;\n}\n\ncaption {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n  color: #6c757d;\n  text-align: left;\n}\n\nth {\n  text-align: inherit;\n  text-align: -webkit-match-parent;\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n  border-color: inherit;\n  border-style: solid;\n  border-width: 0;\n}\n\nlabel {\n  display: inline-block;\n}\n\nbutton {\n  border-radius: 0;\n}\n\nbutton:focus:not(:focus-visible) {\n  outline: 0;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n[role=button] {\n  cursor: pointer;\n}\n\nselect {\n  word-wrap: normal;\n}\nselect:disabled {\n  opacity: 1;\n}\n\n[list]::-webkit-calendar-picker-indicator {\n  display: none;\n}\n\nbutton,\n[type=button],\n[type=reset],\n[type=submit] {\n  -webkit-appearance: button;\n}\nbutton:not(:disabled),\n[type=button]:not(:disabled),\n[type=reset]:not(:disabled),\n[type=submit]:not(:disabled) {\n  cursor: pointer;\n}\n\n::-moz-focus-inner {\n  padding: 0;\n  border-style: none;\n}\n\ntextarea {\n  resize: vertical;\n}\n\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  float: left;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 0.5rem;\n  font-size: calc(1.275rem + 0.3vw);\n  line-height: inherit;\n}\n@media (min-width: 1200px) {\n  legend {\n    font-size: 1.5rem;\n  }\n}\nlegend + * {\n  clear: left;\n}\n\n::-webkit-datetime-edit-fields-wrapper,\n::-webkit-datetime-edit-text,\n::-webkit-datetime-edit-minute,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-year-field {\n  padding: 0;\n}\n\n::-webkit-inner-spin-button {\n  height: auto;\n}\n\n[type=search] {\n  outline-offset: -2px;\n  -webkit-appearance: textfield;\n}\n\n/* rtl:raw:\n[type=\"tel\"],\n[type=\"url\"],\n[type=\"email\"],\n[type=\"number\"] {\n  direction: ltr;\n}\n*/\n::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n::-webkit-color-swatch-wrapper {\n  padding: 0;\n}\n\n::file-selector-button {\n  font: inherit;\n}\n\n::-webkit-file-upload-button {\n  font: inherit;\n  -webkit-appearance: button;\n}\n\noutput {\n  display: inline-block;\n}\n\niframe {\n  border: 0;\n}\n\nsummary {\n  display: list-item;\n  cursor: pointer;\n}\n\nprogress {\n  vertical-align: baseline;\n}\n\n[hidden] {\n  display: none !important;\n}\n\n.lead {\n  font-size: 1.25rem;\n  font-weight: 300;\n}\n\n.display-1 {\n  font-size: calc(1.625rem + 4.5vw);\n  font-weight: 300;\n  line-height: 1.2;\n}\n@media (min-width: 1200px) {\n  .display-1 {\n    font-size: 5rem;\n  }\n}\n\n.display-2 {\n  font-size: calc(1.575rem + 3.9vw);\n  font-weight: 300;\n  line-height: 1.2;\n}\n@media (min-width: 1200px) {\n  .display-2 {\n    font-size: 4.5rem;\n  }\n}\n\n.display-3 {\n  font-size: calc(1.525rem + 3.3vw);\n  font-weight: 300;\n  line-height: 1.2;\n}\n@media (min-width: 1200px) {\n  .display-3 {\n    font-size: 4rem;\n  }\n}\n\n.display-4 {\n  font-size: calc(1.475rem + 2.7vw);\n  font-weight: 300;\n  line-height: 1.2;\n}\n@media (min-width: 1200px) {\n  .display-4 {\n    font-size: 3.5rem;\n  }\n}\n\n.display-5 {\n  font-size: calc(1.425rem + 2.1vw);\n  font-weight: 300;\n  line-height: 1.2;\n}\n@media (min-width: 1200px) {\n  .display-5 {\n    font-size: 3rem;\n  }\n}\n\n.display-6 {\n  font-size: calc(1.375rem + 1.5vw);\n  font-weight: 300;\n  line-height: 1.2;\n}\n@media (min-width: 1200px) {\n  .display-6 {\n    font-size: 2.5rem;\n  }\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline-item {\n  display: inline-block;\n}\n.list-inline-item:not(:last-child) {\n  margin-right: 0.5rem;\n}\n\n.initialism {\n  font-size: 0.875em;\n  text-transform: uppercase;\n}\n\n.blockquote {\n  margin-bottom: 1rem;\n  font-size: 1.25rem;\n}\n.blockquote > :last-child {\n  margin-bottom: 0;\n}\n\n.blockquote-footer {\n  margin-top: -1rem;\n  margin-bottom: 1rem;\n  font-size: 0.875em;\n  color: #6c757d;\n}\n.blockquote-footer::before {\n  content: \"— \";\n}\n\n.img-fluid {\n  max-width: 100%;\n  height: auto;\n}\n\n.img-thumbnail {\n  padding: 0.25rem;\n  background-color: #fff;\n  border: 1px solid #dee2e6;\n  border-radius: 0.25rem;\n  max-width: 100%;\n  height: auto;\n}\n\n.figure {\n  display: inline-block;\n}\n\n.figure-img {\n  margin-bottom: 0.5rem;\n  line-height: 1;\n}\n\n.figure-caption {\n  font-size: 0.875em;\n  color: #6c757d;\n}\n\n.container,\n.container-fluid,\n.container-xxl,\n.container-xl,\n.container-lg,\n.container-md,\n.container-sm {\n  width: 100%;\n  padding-right: var(--bs-gutter-x, 0.75rem);\n  padding-left: var(--bs-gutter-x, 0.75rem);\n  margin-right: auto;\n  margin-left: auto;\n}\n\n@media (min-width: 576px) {\n  .container-sm, .container {\n    max-width: 540px;\n  }\n}\n@media (min-width: 768px) {\n  .container-md, .container-sm, .container {\n    max-width: 720px;\n  }\n}\n@media (min-width: 992px) {\n  .container-lg, .container-md, .container-sm, .container {\n    max-width: 960px;\n  }\n}\n@media (min-width: 1200px) {\n  .container-xl, .container-lg, .container-md, .container-sm, .container {\n    max-width: 1140px;\n  }\n}\n@media (min-width: 1400px) {\n  .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container {\n    max-width: 1320px;\n  }\n}\n.row {\n  --bs-gutter-x: 1.5rem;\n  --bs-gutter-y: 0;\n  display: flex;\n  flex-wrap: wrap;\n  margin-top: calc(var(--bs-gutter-y) * -1);\n  margin-right: calc(var(--bs-gutter-x) * -.5);\n  margin-left: calc(var(--bs-gutter-x) * -.5);\n}\n.row > * {\n  flex-shrink: 0;\n  width: 100%;\n  max-width: 100%;\n  padding-right: calc(var(--bs-gutter-x) * .5);\n  padding-left: calc(var(--bs-gutter-x) * .5);\n  margin-top: var(--bs-gutter-y);\n}\n\n.col {\n  flex: 1 0 0%;\n}\n\n.row-cols-auto > * {\n  flex: 0 0 auto;\n  width: auto;\n}\n\n.row-cols-1 > * {\n  flex: 0 0 auto;\n  width: 100%;\n}\n\n.row-cols-2 > * {\n  flex: 0 0 auto;\n  width: 50%;\n}\n\n.row-cols-3 > * {\n  flex: 0 0 auto;\n  width: 33.3333333333%;\n}\n\n.row-cols-4 > * {\n  flex: 0 0 auto;\n  width: 25%;\n}\n\n.row-cols-5 > * {\n  flex: 0 0 auto;\n  width: 20%;\n}\n\n.row-cols-6 > * {\n  flex: 0 0 auto;\n  width: 16.6666666667%;\n}\n\n@media (min-width: 576px) {\n  .col-sm {\n    flex: 1 0 0%;\n  }\n\n  .row-cols-sm-auto > * {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .row-cols-sm-1 > * {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .row-cols-sm-2 > * {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .row-cols-sm-3 > * {\n    flex: 0 0 auto;\n    width: 33.3333333333%;\n  }\n\n  .row-cols-sm-4 > * {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .row-cols-sm-5 > * {\n    flex: 0 0 auto;\n    width: 20%;\n  }\n\n  .row-cols-sm-6 > * {\n    flex: 0 0 auto;\n    width: 16.6666666667%;\n  }\n}\n@media (min-width: 768px) {\n  .col-md {\n    flex: 1 0 0%;\n  }\n\n  .row-cols-md-auto > * {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .row-cols-md-1 > * {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .row-cols-md-2 > * {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .row-cols-md-3 > * {\n    flex: 0 0 auto;\n    width: 33.3333333333%;\n  }\n\n  .row-cols-md-4 > * {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .row-cols-md-5 > * {\n    flex: 0 0 auto;\n    width: 20%;\n  }\n\n  .row-cols-md-6 > * {\n    flex: 0 0 auto;\n    width: 16.6666666667%;\n  }\n}\n@media (min-width: 992px) {\n  .col-lg {\n    flex: 1 0 0%;\n  }\n\n  .row-cols-lg-auto > * {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .row-cols-lg-1 > * {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .row-cols-lg-2 > * {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .row-cols-lg-3 > * {\n    flex: 0 0 auto;\n    width: 33.3333333333%;\n  }\n\n  .row-cols-lg-4 > * {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .row-cols-lg-5 > * {\n    flex: 0 0 auto;\n    width: 20%;\n  }\n\n  .row-cols-lg-6 > * {\n    flex: 0 0 auto;\n    width: 16.6666666667%;\n  }\n}\n@media (min-width: 1200px) {\n  .col-xl {\n    flex: 1 0 0%;\n  }\n\n  .row-cols-xl-auto > * {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .row-cols-xl-1 > * {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .row-cols-xl-2 > * {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .row-cols-xl-3 > * {\n    flex: 0 0 auto;\n    width: 33.3333333333%;\n  }\n\n  .row-cols-xl-4 > * {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .row-cols-xl-5 > * {\n    flex: 0 0 auto;\n    width: 20%;\n  }\n\n  .row-cols-xl-6 > * {\n    flex: 0 0 auto;\n    width: 16.6666666667%;\n  }\n}\n@media (min-width: 1400px) {\n  .col-xxl {\n    flex: 1 0 0%;\n  }\n\n  .row-cols-xxl-auto > * {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .row-cols-xxl-1 > * {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .row-cols-xxl-2 > * {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .row-cols-xxl-3 > * {\n    flex: 0 0 auto;\n    width: 33.3333333333%;\n  }\n\n  .row-cols-xxl-4 > * {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .row-cols-xxl-5 > * {\n    flex: 0 0 auto;\n    width: 20%;\n  }\n\n  .row-cols-xxl-6 > * {\n    flex: 0 0 auto;\n    width: 16.6666666667%;\n  }\n}\n.col-auto {\n  flex: 0 0 auto;\n  width: auto;\n}\n\n.col-1 {\n  flex: 0 0 auto;\n  width: 8.33333333%;\n}\n\n.col-2 {\n  flex: 0 0 auto;\n  width: 16.66666667%;\n}\n\n.col-3 {\n  flex: 0 0 auto;\n  width: 25%;\n}\n\n.col-4 {\n  flex: 0 0 auto;\n  width: 33.33333333%;\n}\n\n.col-5 {\n  flex: 0 0 auto;\n  width: 41.66666667%;\n}\n\n.col-6 {\n  flex: 0 0 auto;\n  width: 50%;\n}\n\n.col-7 {\n  flex: 0 0 auto;\n  width: 58.33333333%;\n}\n\n.col-8 {\n  flex: 0 0 auto;\n  width: 66.66666667%;\n}\n\n.col-9 {\n  flex: 0 0 auto;\n  width: 75%;\n}\n\n.col-10 {\n  flex: 0 0 auto;\n  width: 83.33333333%;\n}\n\n.col-11 {\n  flex: 0 0 auto;\n  width: 91.66666667%;\n}\n\n.col-12 {\n  flex: 0 0 auto;\n  width: 100%;\n}\n\n.offset-1 {\n  margin-left: 8.33333333%;\n}\n\n.offset-2 {\n  margin-left: 16.66666667%;\n}\n\n.offset-3 {\n  margin-left: 25%;\n}\n\n.offset-4 {\n  margin-left: 33.33333333%;\n}\n\n.offset-5 {\n  margin-left: 41.66666667%;\n}\n\n.offset-6 {\n  margin-left: 50%;\n}\n\n.offset-7 {\n  margin-left: 58.33333333%;\n}\n\n.offset-8 {\n  margin-left: 66.66666667%;\n}\n\n.offset-9 {\n  margin-left: 75%;\n}\n\n.offset-10 {\n  margin-left: 83.33333333%;\n}\n\n.offset-11 {\n  margin-left: 91.66666667%;\n}\n\n.g-0,\n.gx-0 {\n  --bs-gutter-x: 0;\n}\n\n.g-0,\n.gy-0 {\n  --bs-gutter-y: 0;\n}\n\n.g-1,\n.gx-1 {\n  --bs-gutter-x: 0.25rem;\n}\n\n.g-1,\n.gy-1 {\n  --bs-gutter-y: 0.25rem;\n}\n\n.g-2,\n.gx-2 {\n  --bs-gutter-x: 0.5rem;\n}\n\n.g-2,\n.gy-2 {\n  --bs-gutter-y: 0.5rem;\n}\n\n.g-3,\n.gx-3 {\n  --bs-gutter-x: 1rem;\n}\n\n.g-3,\n.gy-3 {\n  --bs-gutter-y: 1rem;\n}\n\n.g-4,\n.gx-4 {\n  --bs-gutter-x: 1.5rem;\n}\n\n.g-4,\n.gy-4 {\n  --bs-gutter-y: 1.5rem;\n}\n\n.g-5,\n.gx-5 {\n  --bs-gutter-x: 3rem;\n}\n\n.g-5,\n.gy-5 {\n  --bs-gutter-y: 3rem;\n}\n\n@media (min-width: 576px) {\n  .col-sm-auto {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .col-sm-1 {\n    flex: 0 0 auto;\n    width: 8.33333333%;\n  }\n\n  .col-sm-2 {\n    flex: 0 0 auto;\n    width: 16.66666667%;\n  }\n\n  .col-sm-3 {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .col-sm-4 {\n    flex: 0 0 auto;\n    width: 33.33333333%;\n  }\n\n  .col-sm-5 {\n    flex: 0 0 auto;\n    width: 41.66666667%;\n  }\n\n  .col-sm-6 {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .col-sm-7 {\n    flex: 0 0 auto;\n    width: 58.33333333%;\n  }\n\n  .col-sm-8 {\n    flex: 0 0 auto;\n    width: 66.66666667%;\n  }\n\n  .col-sm-9 {\n    flex: 0 0 auto;\n    width: 75%;\n  }\n\n  .col-sm-10 {\n    flex: 0 0 auto;\n    width: 83.33333333%;\n  }\n\n  .col-sm-11 {\n    flex: 0 0 auto;\n    width: 91.66666667%;\n  }\n\n  .col-sm-12 {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .offset-sm-0 {\n    margin-left: 0;\n  }\n\n  .offset-sm-1 {\n    margin-left: 8.33333333%;\n  }\n\n  .offset-sm-2 {\n    margin-left: 16.66666667%;\n  }\n\n  .offset-sm-3 {\n    margin-left: 25%;\n  }\n\n  .offset-sm-4 {\n    margin-left: 33.33333333%;\n  }\n\n  .offset-sm-5 {\n    margin-left: 41.66666667%;\n  }\n\n  .offset-sm-6 {\n    margin-left: 50%;\n  }\n\n  .offset-sm-7 {\n    margin-left: 58.33333333%;\n  }\n\n  .offset-sm-8 {\n    margin-left: 66.66666667%;\n  }\n\n  .offset-sm-9 {\n    margin-left: 75%;\n  }\n\n  .offset-sm-10 {\n    margin-left: 83.33333333%;\n  }\n\n  .offset-sm-11 {\n    margin-left: 91.66666667%;\n  }\n\n  .g-sm-0,\n.gx-sm-0 {\n    --bs-gutter-x: 0;\n  }\n\n  .g-sm-0,\n.gy-sm-0 {\n    --bs-gutter-y: 0;\n  }\n\n  .g-sm-1,\n.gx-sm-1 {\n    --bs-gutter-x: 0.25rem;\n  }\n\n  .g-sm-1,\n.gy-sm-1 {\n    --bs-gutter-y: 0.25rem;\n  }\n\n  .g-sm-2,\n.gx-sm-2 {\n    --bs-gutter-x: 0.5rem;\n  }\n\n  .g-sm-2,\n.gy-sm-2 {\n    --bs-gutter-y: 0.5rem;\n  }\n\n  .g-sm-3,\n.gx-sm-3 {\n    --bs-gutter-x: 1rem;\n  }\n\n  .g-sm-3,\n.gy-sm-3 {\n    --bs-gutter-y: 1rem;\n  }\n\n  .g-sm-4,\n.gx-sm-4 {\n    --bs-gutter-x: 1.5rem;\n  }\n\n  .g-sm-4,\n.gy-sm-4 {\n    --bs-gutter-y: 1.5rem;\n  }\n\n  .g-sm-5,\n.gx-sm-5 {\n    --bs-gutter-x: 3rem;\n  }\n\n  .g-sm-5,\n.gy-sm-5 {\n    --bs-gutter-y: 3rem;\n  }\n}\n@media (min-width: 768px) {\n  .col-md-auto {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .col-md-1 {\n    flex: 0 0 auto;\n    width: 8.33333333%;\n  }\n\n  .col-md-2 {\n    flex: 0 0 auto;\n    width: 16.66666667%;\n  }\n\n  .col-md-3 {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .col-md-4 {\n    flex: 0 0 auto;\n    width: 33.33333333%;\n  }\n\n  .col-md-5 {\n    flex: 0 0 auto;\n    width: 41.66666667%;\n  }\n\n  .col-md-6 {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .col-md-7 {\n    flex: 0 0 auto;\n    width: 58.33333333%;\n  }\n\n  .col-md-8 {\n    flex: 0 0 auto;\n    width: 66.66666667%;\n  }\n\n  .col-md-9 {\n    flex: 0 0 auto;\n    width: 75%;\n  }\n\n  .col-md-10 {\n    flex: 0 0 auto;\n    width: 83.33333333%;\n  }\n\n  .col-md-11 {\n    flex: 0 0 auto;\n    width: 91.66666667%;\n  }\n\n  .col-md-12 {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .offset-md-0 {\n    margin-left: 0;\n  }\n\n  .offset-md-1 {\n    margin-left: 8.33333333%;\n  }\n\n  .offset-md-2 {\n    margin-left: 16.66666667%;\n  }\n\n  .offset-md-3 {\n    margin-left: 25%;\n  }\n\n  .offset-md-4 {\n    margin-left: 33.33333333%;\n  }\n\n  .offset-md-5 {\n    margin-left: 41.66666667%;\n  }\n\n  .offset-md-6 {\n    margin-left: 50%;\n  }\n\n  .offset-md-7 {\n    margin-left: 58.33333333%;\n  }\n\n  .offset-md-8 {\n    margin-left: 66.66666667%;\n  }\n\n  .offset-md-9 {\n    margin-left: 75%;\n  }\n\n  .offset-md-10 {\n    margin-left: 83.33333333%;\n  }\n\n  .offset-md-11 {\n    margin-left: 91.66666667%;\n  }\n\n  .g-md-0,\n.gx-md-0 {\n    --bs-gutter-x: 0;\n  }\n\n  .g-md-0,\n.gy-md-0 {\n    --bs-gutter-y: 0;\n  }\n\n  .g-md-1,\n.gx-md-1 {\n    --bs-gutter-x: 0.25rem;\n  }\n\n  .g-md-1,\n.gy-md-1 {\n    --bs-gutter-y: 0.25rem;\n  }\n\n  .g-md-2,\n.gx-md-2 {\n    --bs-gutter-x: 0.5rem;\n  }\n\n  .g-md-2,\n.gy-md-2 {\n    --bs-gutter-y: 0.5rem;\n  }\n\n  .g-md-3,\n.gx-md-3 {\n    --bs-gutter-x: 1rem;\n  }\n\n  .g-md-3,\n.gy-md-3 {\n    --bs-gutter-y: 1rem;\n  }\n\n  .g-md-4,\n.gx-md-4 {\n    --bs-gutter-x: 1.5rem;\n  }\n\n  .g-md-4,\n.gy-md-4 {\n    --bs-gutter-y: 1.5rem;\n  }\n\n  .g-md-5,\n.gx-md-5 {\n    --bs-gutter-x: 3rem;\n  }\n\n  .g-md-5,\n.gy-md-5 {\n    --bs-gutter-y: 3rem;\n  }\n}\n@media (min-width: 992px) {\n  .col-lg-auto {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .col-lg-1 {\n    flex: 0 0 auto;\n    width: 8.33333333%;\n  }\n\n  .col-lg-2 {\n    flex: 0 0 auto;\n    width: 16.66666667%;\n  }\n\n  .col-lg-3 {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .col-lg-4 {\n    flex: 0 0 auto;\n    width: 33.33333333%;\n  }\n\n  .col-lg-5 {\n    flex: 0 0 auto;\n    width: 41.66666667%;\n  }\n\n  .col-lg-6 {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .col-lg-7 {\n    flex: 0 0 auto;\n    width: 58.33333333%;\n  }\n\n  .col-lg-8 {\n    flex: 0 0 auto;\n    width: 66.66666667%;\n  }\n\n  .col-lg-9 {\n    flex: 0 0 auto;\n    width: 75%;\n  }\n\n  .col-lg-10 {\n    flex: 0 0 auto;\n    width: 83.33333333%;\n  }\n\n  .col-lg-11 {\n    flex: 0 0 auto;\n    width: 91.66666667%;\n  }\n\n  .col-lg-12 {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .offset-lg-0 {\n    margin-left: 0;\n  }\n\n  .offset-lg-1 {\n    margin-left: 8.33333333%;\n  }\n\n  .offset-lg-2 {\n    margin-left: 16.66666667%;\n  }\n\n  .offset-lg-3 {\n    margin-left: 25%;\n  }\n\n  .offset-lg-4 {\n    margin-left: 33.33333333%;\n  }\n\n  .offset-lg-5 {\n    margin-left: 41.66666667%;\n  }\n\n  .offset-lg-6 {\n    margin-left: 50%;\n  }\n\n  .offset-lg-7 {\n    margin-left: 58.33333333%;\n  }\n\n  .offset-lg-8 {\n    margin-left: 66.66666667%;\n  }\n\n  .offset-lg-9 {\n    margin-left: 75%;\n  }\n\n  .offset-lg-10 {\n    margin-left: 83.33333333%;\n  }\n\n  .offset-lg-11 {\n    margin-left: 91.66666667%;\n  }\n\n  .g-lg-0,\n.gx-lg-0 {\n    --bs-gutter-x: 0;\n  }\n\n  .g-lg-0,\n.gy-lg-0 {\n    --bs-gutter-y: 0;\n  }\n\n  .g-lg-1,\n.gx-lg-1 {\n    --bs-gutter-x: 0.25rem;\n  }\n\n  .g-lg-1,\n.gy-lg-1 {\n    --bs-gutter-y: 0.25rem;\n  }\n\n  .g-lg-2,\n.gx-lg-2 {\n    --bs-gutter-x: 0.5rem;\n  }\n\n  .g-lg-2,\n.gy-lg-2 {\n    --bs-gutter-y: 0.5rem;\n  }\n\n  .g-lg-3,\n.gx-lg-3 {\n    --bs-gutter-x: 1rem;\n  }\n\n  .g-lg-3,\n.gy-lg-3 {\n    --bs-gutter-y: 1rem;\n  }\n\n  .g-lg-4,\n.gx-lg-4 {\n    --bs-gutter-x: 1.5rem;\n  }\n\n  .g-lg-4,\n.gy-lg-4 {\n    --bs-gutter-y: 1.5rem;\n  }\n\n  .g-lg-5,\n.gx-lg-5 {\n    --bs-gutter-x: 3rem;\n  }\n\n  .g-lg-5,\n.gy-lg-5 {\n    --bs-gutter-y: 3rem;\n  }\n}\n@media (min-width: 1200px) {\n  .col-xl-auto {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .col-xl-1 {\n    flex: 0 0 auto;\n    width: 8.33333333%;\n  }\n\n  .col-xl-2 {\n    flex: 0 0 auto;\n    width: 16.66666667%;\n  }\n\n  .col-xl-3 {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .col-xl-4 {\n    flex: 0 0 auto;\n    width: 33.33333333%;\n  }\n\n  .col-xl-5 {\n    flex: 0 0 auto;\n    width: 41.66666667%;\n  }\n\n  .col-xl-6 {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .col-xl-7 {\n    flex: 0 0 auto;\n    width: 58.33333333%;\n  }\n\n  .col-xl-8 {\n    flex: 0 0 auto;\n    width: 66.66666667%;\n  }\n\n  .col-xl-9 {\n    flex: 0 0 auto;\n    width: 75%;\n  }\n\n  .col-xl-10 {\n    flex: 0 0 auto;\n    width: 83.33333333%;\n  }\n\n  .col-xl-11 {\n    flex: 0 0 auto;\n    width: 91.66666667%;\n  }\n\n  .col-xl-12 {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .offset-xl-0 {\n    margin-left: 0;\n  }\n\n  .offset-xl-1 {\n    margin-left: 8.33333333%;\n  }\n\n  .offset-xl-2 {\n    margin-left: 16.66666667%;\n  }\n\n  .offset-xl-3 {\n    margin-left: 25%;\n  }\n\n  .offset-xl-4 {\n    margin-left: 33.33333333%;\n  }\n\n  .offset-xl-5 {\n    margin-left: 41.66666667%;\n  }\n\n  .offset-xl-6 {\n    margin-left: 50%;\n  }\n\n  .offset-xl-7 {\n    margin-left: 58.33333333%;\n  }\n\n  .offset-xl-8 {\n    margin-left: 66.66666667%;\n  }\n\n  .offset-xl-9 {\n    margin-left: 75%;\n  }\n\n  .offset-xl-10 {\n    margin-left: 83.33333333%;\n  }\n\n  .offset-xl-11 {\n    margin-left: 91.66666667%;\n  }\n\n  .g-xl-0,\n.gx-xl-0 {\n    --bs-gutter-x: 0;\n  }\n\n  .g-xl-0,\n.gy-xl-0 {\n    --bs-gutter-y: 0;\n  }\n\n  .g-xl-1,\n.gx-xl-1 {\n    --bs-gutter-x: 0.25rem;\n  }\n\n  .g-xl-1,\n.gy-xl-1 {\n    --bs-gutter-y: 0.25rem;\n  }\n\n  .g-xl-2,\n.gx-xl-2 {\n    --bs-gutter-x: 0.5rem;\n  }\n\n  .g-xl-2,\n.gy-xl-2 {\n    --bs-gutter-y: 0.5rem;\n  }\n\n  .g-xl-3,\n.gx-xl-3 {\n    --bs-gutter-x: 1rem;\n  }\n\n  .g-xl-3,\n.gy-xl-3 {\n    --bs-gutter-y: 1rem;\n  }\n\n  .g-xl-4,\n.gx-xl-4 {\n    --bs-gutter-x: 1.5rem;\n  }\n\n  .g-xl-4,\n.gy-xl-4 {\n    --bs-gutter-y: 1.5rem;\n  }\n\n  .g-xl-5,\n.gx-xl-5 {\n    --bs-gutter-x: 3rem;\n  }\n\n  .g-xl-5,\n.gy-xl-5 {\n    --bs-gutter-y: 3rem;\n  }\n}\n@media (min-width: 1400px) {\n  .col-xxl-auto {\n    flex: 0 0 auto;\n    width: auto;\n  }\n\n  .col-xxl-1 {\n    flex: 0 0 auto;\n    width: 8.33333333%;\n  }\n\n  .col-xxl-2 {\n    flex: 0 0 auto;\n    width: 16.66666667%;\n  }\n\n  .col-xxl-3 {\n    flex: 0 0 auto;\n    width: 25%;\n  }\n\n  .col-xxl-4 {\n    flex: 0 0 auto;\n    width: 33.33333333%;\n  }\n\n  .col-xxl-5 {\n    flex: 0 0 auto;\n    width: 41.66666667%;\n  }\n\n  .col-xxl-6 {\n    flex: 0 0 auto;\n    width: 50%;\n  }\n\n  .col-xxl-7 {\n    flex: 0 0 auto;\n    width: 58.33333333%;\n  }\n\n  .col-xxl-8 {\n    flex: 0 0 auto;\n    width: 66.66666667%;\n  }\n\n  .col-xxl-9 {\n    flex: 0 0 auto;\n    width: 75%;\n  }\n\n  .col-xxl-10 {\n    flex: 0 0 auto;\n    width: 83.33333333%;\n  }\n\n  .col-xxl-11 {\n    flex: 0 0 auto;\n    width: 91.66666667%;\n  }\n\n  .col-xxl-12 {\n    flex: 0 0 auto;\n    width: 100%;\n  }\n\n  .offset-xxl-0 {\n    margin-left: 0;\n  }\n\n  .offset-xxl-1 {\n    margin-left: 8.33333333%;\n  }\n\n  .offset-xxl-2 {\n    margin-left: 16.66666667%;\n  }\n\n  .offset-xxl-3 {\n    margin-left: 25%;\n  }\n\n  .offset-xxl-4 {\n    margin-left: 33.33333333%;\n  }\n\n  .offset-xxl-5 {\n    margin-left: 41.66666667%;\n  }\n\n  .offset-xxl-6 {\n    margin-left: 50%;\n  }\n\n  .offset-xxl-7 {\n    margin-left: 58.33333333%;\n  }\n\n  .offset-xxl-8 {\n    margin-left: 66.66666667%;\n  }\n\n  .offset-xxl-9 {\n    margin-left: 75%;\n  }\n\n  .offset-xxl-10 {\n    margin-left: 83.33333333%;\n  }\n\n  .offset-xxl-11 {\n    margin-left: 91.66666667%;\n  }\n\n  .g-xxl-0,\n.gx-xxl-0 {\n    --bs-gutter-x: 0;\n  }\n\n  .g-xxl-0,\n.gy-xxl-0 {\n    --bs-gutter-y: 0;\n  }\n\n  .g-xxl-1,\n.gx-xxl-1 {\n    --bs-gutter-x: 0.25rem;\n  }\n\n  .g-xxl-1,\n.gy-xxl-1 {\n    --bs-gutter-y: 0.25rem;\n  }\n\n  .g-xxl-2,\n.gx-xxl-2 {\n    --bs-gutter-x: 0.5rem;\n  }\n\n  .g-xxl-2,\n.gy-xxl-2 {\n    --bs-gutter-y: 0.5rem;\n  }\n\n  .g-xxl-3,\n.gx-xxl-3 {\n    --bs-gutter-x: 1rem;\n  }\n\n  .g-xxl-3,\n.gy-xxl-3 {\n    --bs-gutter-y: 1rem;\n  }\n\n  .g-xxl-4,\n.gx-xxl-4 {\n    --bs-gutter-x: 1.5rem;\n  }\n\n  .g-xxl-4,\n.gy-xxl-4 {\n    --bs-gutter-y: 1.5rem;\n  }\n\n  .g-xxl-5,\n.gx-xxl-5 {\n    --bs-gutter-x: 3rem;\n  }\n\n  .g-xxl-5,\n.gy-xxl-5 {\n    --bs-gutter-y: 3rem;\n  }\n}\n.table {\n  --bs-table-bg: transparent;\n  --bs-table-accent-bg: transparent;\n  --bs-table-striped-color: #212529;\n  --bs-table-striped-bg: rgba(0, 0, 0, 0.05);\n  --bs-table-active-color: #212529;\n  --bs-table-active-bg: rgba(0, 0, 0, 0.1);\n  --bs-table-hover-color: #212529;\n  --bs-table-hover-bg: rgba(0, 0, 0, 0.075);\n  width: 100%;\n  margin-bottom: 1rem;\n  color: #212529;\n  vertical-align: top;\n  border-color: #dee2e6;\n}\n.table > :not(caption) > * > * {\n  padding: 0.5rem 0.5rem;\n  background-color: var(--bs-table-bg);\n  border-bottom-width: 1px;\n  box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg);\n}\n.table > tbody {\n  vertical-align: inherit;\n}\n.table > thead {\n  vertical-align: bottom;\n}\n.table > :not(:last-child) > :last-child > * {\n  border-bottom-color: currentColor;\n}\n\n.caption-top {\n  caption-side: top;\n}\n\n.table-sm > :not(caption) > * > * {\n  padding: 0.25rem 0.25rem;\n}\n\n.table-bordered > :not(caption) > * {\n  border-width: 1px 0;\n}\n.table-bordered > :not(caption) > * > * {\n  border-width: 0 1px;\n}\n\n.table-borderless > :not(caption) > * > * {\n  border-bottom-width: 0;\n}\n\n.table-striped > tbody > tr:nth-of-type(odd) {\n  --bs-table-accent-bg: var(--bs-table-striped-bg);\n  color: var(--bs-table-striped-color);\n}\n\n.table-active {\n  --bs-table-accent-bg: var(--bs-table-active-bg);\n  color: var(--bs-table-active-color);\n}\n\n.table-hover > tbody > tr:hover {\n  --bs-table-accent-bg: var(--bs-table-hover-bg);\n  color: var(--bs-table-hover-color);\n}\n\n.table-primary {\n  --bs-table-bg: #cfe2ff;\n  --bs-table-striped-bg: #c5d7f2;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #bacbe6;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #bfd1ec;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #bacbe6;\n}\n\n.table-secondary {\n  --bs-table-bg: #e2e3e5;\n  --bs-table-striped-bg: #d7d8da;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #cbccce;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #d1d2d4;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #cbccce;\n}\n\n.table-success {\n  --bs-table-bg: #d1e7dd;\n  --bs-table-striped-bg: #c7dbd2;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #bcd0c7;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #c1d6cc;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #bcd0c7;\n}\n\n.table-info {\n  --bs-table-bg: #cff4fc;\n  --bs-table-striped-bg: #c5e8ef;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #badce3;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #bfe2e9;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #badce3;\n}\n\n.table-warning {\n  --bs-table-bg: #fff3cd;\n  --bs-table-striped-bg: #f2e7c3;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #e6dbb9;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #ece1be;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #e6dbb9;\n}\n\n.table-danger {\n  --bs-table-bg: #f8d7da;\n  --bs-table-striped-bg: #eccccf;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #dfc2c4;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #e5c7ca;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #dfc2c4;\n}\n\n.table-light {\n  --bs-table-bg: #f8f9fa;\n  --bs-table-striped-bg: #ecedee;\n  --bs-table-striped-color: #000;\n  --bs-table-active-bg: #dfe0e1;\n  --bs-table-active-color: #000;\n  --bs-table-hover-bg: #e5e6e7;\n  --bs-table-hover-color: #000;\n  color: #000;\n  border-color: #dfe0e1;\n}\n\n.table-dark {\n  --bs-table-bg: #212529;\n  --bs-table-striped-bg: #2c3034;\n  --bs-table-striped-color: #fff;\n  --bs-table-active-bg: #373b3e;\n  --bs-table-active-color: #fff;\n  --bs-table-hover-bg: #323539;\n  --bs-table-hover-color: #fff;\n  color: #fff;\n  border-color: #373b3e;\n}\n\n.table-responsive {\n  overflow-x: auto;\n  -webkit-overflow-scrolling: touch;\n}\n\n@media (max-width: 575.98px) {\n  .table-responsive-sm {\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n}\n@media (max-width: 767.98px) {\n  .table-responsive-md {\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n}\n@media (max-width: 991.98px) {\n  .table-responsive-lg {\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n}\n@media (max-width: 1199.98px) {\n  .table-responsive-xl {\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n}\n@media (max-width: 1399.98px) {\n  .table-responsive-xxl {\n    overflow-x: auto;\n    -webkit-overflow-scrolling: touch;\n  }\n}\n.form-label {\n  margin-bottom: 0.5rem;\n}\n\n.col-form-label {\n  padding-top: calc(0.375rem + 1px);\n  padding-bottom: calc(0.375rem + 1px);\n  margin-bottom: 0;\n  font-size: inherit;\n  line-height: 1.5;\n}\n\n.col-form-label-lg {\n  padding-top: calc(0.5rem + 1px);\n  padding-bottom: calc(0.5rem + 1px);\n  font-size: 1.25rem;\n}\n\n.col-form-label-sm {\n  padding-top: calc(0.25rem + 1px);\n  padding-bottom: calc(0.25rem + 1px);\n  font-size: 0.875rem;\n}\n\n.form-text {\n  margin-top: 0.25rem;\n  font-size: 0.875em;\n  color: #6c757d;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ced4da;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  border-radius: 0.25rem;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-control {\n    transition: none;\n  }\n}\n.form-control[type=file] {\n  overflow: hidden;\n}\n.form-control[type=file]:not(:disabled):not([readonly]) {\n  cursor: pointer;\n}\n.form-control:focus {\n  color: #212529;\n  background-color: #fff;\n  border-color: #86b7fe;\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n.form-control::-webkit-date-and-time-value {\n  height: 1.5em;\n}\n.form-control::-moz-placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n.form-control::placeholder {\n  color: #6c757d;\n  opacity: 1;\n}\n.form-control:disabled, .form-control[readonly] {\n  background-color: #e9ecef;\n  opacity: 1;\n}\n.form-control::file-selector-button {\n  padding: 0.375rem 0.75rem;\n  margin: -0.375rem -0.75rem;\n  -webkit-margin-end: 0.75rem;\n  margin-inline-end: 0.75rem;\n  color: #212529;\n  background-color: #e9ecef;\n  pointer-events: none;\n  border-color: inherit;\n  border-style: solid;\n  border-width: 0;\n  border-inline-end-width: 1px;\n  border-radius: 0;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-control::file-selector-button {\n    transition: none;\n  }\n}\n.form-control:hover:not(:disabled):not([readonly])::file-selector-button {\n  background-color: #dde0e3;\n}\n.form-control::-webkit-file-upload-button {\n  padding: 0.375rem 0.75rem;\n  margin: -0.375rem -0.75rem;\n  -webkit-margin-end: 0.75rem;\n  margin-inline-end: 0.75rem;\n  color: #212529;\n  background-color: #e9ecef;\n  pointer-events: none;\n  border-color: inherit;\n  border-style: solid;\n  border-width: 0;\n  border-inline-end-width: 1px;\n  border-radius: 0;\n  -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-control::-webkit-file-upload-button {\n    -webkit-transition: none;\n    transition: none;\n  }\n}\n.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button {\n  background-color: #dde0e3;\n}\n\n.form-control-plaintext {\n  display: block;\n  width: 100%;\n  padding: 0.375rem 0;\n  margin-bottom: 0;\n  line-height: 1.5;\n  color: #212529;\n  background-color: transparent;\n  border: solid transparent;\n  border-width: 1px 0;\n}\n.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.form-control-sm {\n  min-height: calc(1.5em + (0.5rem + 2px));\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  border-radius: 0.2rem;\n}\n.form-control-sm::file-selector-button {\n  padding: 0.25rem 0.5rem;\n  margin: -0.25rem -0.5rem;\n  -webkit-margin-end: 0.5rem;\n  margin-inline-end: 0.5rem;\n}\n.form-control-sm::-webkit-file-upload-button {\n  padding: 0.25rem 0.5rem;\n  margin: -0.25rem -0.5rem;\n  -webkit-margin-end: 0.5rem;\n  margin-inline-end: 0.5rem;\n}\n\n.form-control-lg {\n  min-height: calc(1.5em + (1rem + 2px));\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  border-radius: 0.3rem;\n}\n.form-control-lg::file-selector-button {\n  padding: 0.5rem 1rem;\n  margin: -0.5rem -1rem;\n  -webkit-margin-end: 1rem;\n  margin-inline-end: 1rem;\n}\n.form-control-lg::-webkit-file-upload-button {\n  padding: 0.5rem 1rem;\n  margin: -0.5rem -1rem;\n  -webkit-margin-end: 1rem;\n  margin-inline-end: 1rem;\n}\n\ntextarea.form-control {\n  min-height: calc(1.5em + (0.75rem + 2px));\n}\ntextarea.form-control-sm {\n  min-height: calc(1.5em + (0.5rem + 2px));\n}\ntextarea.form-control-lg {\n  min-height: calc(1.5em + (1rem + 2px));\n}\n\n.form-control-color {\n  max-width: 3rem;\n  height: auto;\n  padding: 0.375rem;\n}\n.form-control-color:not(:disabled):not([readonly]) {\n  cursor: pointer;\n}\n.form-control-color::-moz-color-swatch {\n  height: 1.5em;\n  border-radius: 0.25rem;\n}\n.form-control-color::-webkit-color-swatch {\n  height: 1.5em;\n  border-radius: 0.25rem;\n}\n\n.form-select {\n  display: block;\n  width: 100%;\n  padding: 0.375rem 2.25rem 0.375rem 0.75rem;\n  -moz-padding-start: calc(0.75rem - 3px);\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  background-color: #fff;\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e\");\n  background-repeat: no-repeat;\n  background-position: right 0.75rem center;\n  background-size: 16px 12px;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-select {\n    transition: none;\n  }\n}\n.form-select:focus {\n  border-color: #86b7fe;\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n.form-select[multiple], .form-select[size]:not([size=\"1\"]) {\n  padding-right: 0.75rem;\n  background-image: none;\n}\n.form-select:disabled {\n  background-color: #e9ecef;\n}\n.form-select:-moz-focusring {\n  color: transparent;\n  text-shadow: 0 0 0 #212529;\n}\n\n.form-select-sm {\n  padding-top: 0.25rem;\n  padding-bottom: 0.25rem;\n  padding-left: 0.5rem;\n  font-size: 0.875rem;\n}\n\n.form-select-lg {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n  padding-left: 1rem;\n  font-size: 1.25rem;\n}\n\n.form-check {\n  display: block;\n  min-height: 1.5rem;\n  padding-left: 1.5em;\n  margin-bottom: 0.125rem;\n}\n.form-check .form-check-input {\n  float: left;\n  margin-left: -1.5em;\n}\n\n.form-check-input {\n  width: 1em;\n  height: 1em;\n  margin-top: 0.25em;\n  vertical-align: top;\n  background-color: #fff;\n  background-repeat: no-repeat;\n  background-position: center;\n  background-size: contain;\n  border: 1px solid rgba(0, 0, 0, 0.25);\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  -webkit-print-color-adjust: exact;\n  color-adjust: exact;\n}\n.form-check-input[type=checkbox] {\n  border-radius: 0.25em;\n}\n.form-check-input[type=radio] {\n  border-radius: 50%;\n}\n.form-check-input:active {\n  filter: brightness(90%);\n}\n.form-check-input:focus {\n  border-color: #86b7fe;\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n.form-check-input:checked {\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n.form-check-input:checked[type=checkbox] {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e\");\n}\n.form-check-input:checked[type=radio] {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e\");\n}\n.form-check-input[type=checkbox]:indeterminate {\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e\");\n}\n.form-check-input:disabled {\n  pointer-events: none;\n  filter: none;\n  opacity: 0.5;\n}\n.form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label {\n  opacity: 0.5;\n}\n\n.form-switch {\n  padding-left: 2.5em;\n}\n.form-switch .form-check-input {\n  width: 2em;\n  margin-left: -2.5em;\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e\");\n  background-position: left center;\n  border-radius: 2em;\n  transition: background-position 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-switch .form-check-input {\n    transition: none;\n  }\n}\n.form-switch .form-check-input:focus {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e\");\n}\n.form-switch .form-check-input:checked {\n  background-position: right center;\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e\");\n}\n\n.form-check-inline {\n  display: inline-block;\n  margin-right: 1rem;\n}\n\n.btn-check {\n  position: absolute;\n  clip: rect(0, 0, 0, 0);\n  pointer-events: none;\n}\n.btn-check[disabled] + .btn, .btn-check:disabled + .btn {\n  pointer-events: none;\n  filter: none;\n  opacity: 0.65;\n}\n\n.form-range {\n  width: 100%;\n  height: 1.5rem;\n  padding: 0;\n  background-color: transparent;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n.form-range:focus {\n  outline: 0;\n}\n.form-range:focus::-webkit-slider-thumb {\n  box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n.form-range:focus::-moz-range-thumb {\n  box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n.form-range::-moz-focus-outer {\n  border: 0;\n}\n.form-range::-webkit-slider-thumb {\n  width: 1rem;\n  height: 1rem;\n  margin-top: -0.25rem;\n  background-color: #0d6efd;\n  border: 0;\n  border-radius: 1rem;\n  -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  -webkit-appearance: none;\n  appearance: none;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-range::-webkit-slider-thumb {\n    -webkit-transition: none;\n    transition: none;\n  }\n}\n.form-range::-webkit-slider-thumb:active {\n  background-color: #b6d4fe;\n}\n.form-range::-webkit-slider-runnable-track {\n  width: 100%;\n  height: 0.5rem;\n  color: transparent;\n  cursor: pointer;\n  background-color: #dee2e6;\n  border-color: transparent;\n  border-radius: 1rem;\n}\n.form-range::-moz-range-thumb {\n  width: 1rem;\n  height: 1rem;\n  background-color: #0d6efd;\n  border: 0;\n  border-radius: 1rem;\n  -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n  -moz-appearance: none;\n  appearance: none;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-range::-moz-range-thumb {\n    -moz-transition: none;\n    transition: none;\n  }\n}\n.form-range::-moz-range-thumb:active {\n  background-color: #b6d4fe;\n}\n.form-range::-moz-range-track {\n  width: 100%;\n  height: 0.5rem;\n  color: transparent;\n  cursor: pointer;\n  background-color: #dee2e6;\n  border-color: transparent;\n  border-radius: 1rem;\n}\n.form-range:disabled {\n  pointer-events: none;\n}\n.form-range:disabled::-webkit-slider-thumb {\n  background-color: #adb5bd;\n}\n.form-range:disabled::-moz-range-thumb {\n  background-color: #adb5bd;\n}\n\n.form-floating {\n  position: relative;\n}\n.form-floating > .form-control,\n.form-floating > .form-select {\n  height: calc(3.5rem + 2px);\n  line-height: 1.25;\n}\n.form-floating > label {\n  position: absolute;\n  top: 0;\n  left: 0;\n  height: 100%;\n  padding: 1rem 0.75rem;\n  pointer-events: none;\n  border: 1px solid transparent;\n  transform-origin: 0 0;\n  transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .form-floating > label {\n    transition: none;\n  }\n}\n.form-floating > .form-control {\n  padding: 1rem 0.75rem;\n}\n.form-floating > .form-control::-moz-placeholder {\n  color: transparent;\n}\n.form-floating > .form-control::placeholder {\n  color: transparent;\n}\n.form-floating > .form-control:not(:-moz-placeholder-shown) {\n  padding-top: 1.625rem;\n  padding-bottom: 0.625rem;\n}\n.form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) {\n  padding-top: 1.625rem;\n  padding-bottom: 0.625rem;\n}\n.form-floating > .form-control:-webkit-autofill {\n  padding-top: 1.625rem;\n  padding-bottom: 0.625rem;\n}\n.form-floating > .form-select {\n  padding-top: 1.625rem;\n  padding-bottom: 0.625rem;\n}\n.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label {\n  opacity: 0.65;\n  transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);\n}\n.form-floating > .form-control:focus ~ label,\n.form-floating > .form-control:not(:placeholder-shown) ~ label,\n.form-floating > .form-select ~ label {\n  opacity: 0.65;\n  transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);\n}\n.form-floating > .form-control:-webkit-autofill ~ label {\n  opacity: 0.65;\n  transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);\n}\n\n.input-group {\n  position: relative;\n  display: flex;\n  flex-wrap: wrap;\n  align-items: stretch;\n  width: 100%;\n}\n.input-group > .form-control,\n.input-group > .form-select {\n  position: relative;\n  flex: 1 1 auto;\n  width: 1%;\n  min-width: 0;\n}\n.input-group > .form-control:focus,\n.input-group > .form-select:focus {\n  z-index: 3;\n}\n.input-group .btn {\n  position: relative;\n  z-index: 2;\n}\n.input-group .btn:focus {\n  z-index: 3;\n}\n\n.input-group-text {\n  display: flex;\n  align-items: center;\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  text-align: center;\n  white-space: nowrap;\n  background-color: #e9ecef;\n  border: 1px solid #ced4da;\n  border-radius: 0.25rem;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .form-select,\n.input-group-lg > .input-group-text,\n.input-group-lg > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  border-radius: 0.3rem;\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .form-select,\n.input-group-sm > .input-group-text,\n.input-group-sm > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  border-radius: 0.2rem;\n}\n\n.input-group-lg > .form-select,\n.input-group-sm > .form-select {\n  padding-right: 3rem;\n}\n\n.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu),\n.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu),\n.input-group.has-validation > .dropdown-toggle:nth-last-child(n+4) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) {\n  margin-left: -1px;\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.valid-feedback {\n  display: none;\n  width: 100%;\n  margin-top: 0.25rem;\n  font-size: 0.875em;\n  color: #198754;\n}\n\n.valid-tooltip {\n  position: absolute;\n  top: 100%;\n  z-index: 5;\n  display: none;\n  max-width: 100%;\n  padding: 0.25rem 0.5rem;\n  margin-top: 0.1rem;\n  font-size: 0.875rem;\n  color: #fff;\n  background-color: rgba(25, 135, 84, 0.9);\n  border-radius: 0.25rem;\n}\n\n.was-validated :valid ~ .valid-feedback,\n.was-validated :valid ~ .valid-tooltip,\n.is-valid ~ .valid-feedback,\n.is-valid ~ .valid-tooltip {\n  display: block;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid {\n  border-color: #198754;\n  padding-right: calc(1.5em + 0.75rem);\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\");\n  background-repeat: no-repeat;\n  background-position: right calc(0.375em + 0.1875rem) center;\n  background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus {\n  border-color: #198754;\n  box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25);\n}\n\n.was-validated textarea.form-control:valid, textarea.form-control.is-valid {\n  padding-right: calc(1.5em + 0.75rem);\n  background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .form-select:valid, .form-select.is-valid {\n  border-color: #198754;\n}\n.was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size=\"1\"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size=\"1\"] {\n  padding-right: 4.125rem;\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e\"), url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\");\n  background-position: right 0.75rem center, center right 2.25rem;\n  background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n.was-validated .form-select:valid:focus, .form-select.is-valid:focus {\n  border-color: #198754;\n  box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25);\n}\n\n.was-validated .form-check-input:valid, .form-check-input.is-valid {\n  border-color: #198754;\n}\n.was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked {\n  background-color: #198754;\n}\n.was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus {\n  box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25);\n}\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n  color: #198754;\n}\n\n.form-check-inline .form-check-input ~ .valid-feedback {\n  margin-left: 0.5em;\n}\n\n.was-validated .input-group .form-control:valid, .input-group .form-control.is-valid,\n.was-validated .input-group .form-select:valid,\n.input-group .form-select.is-valid {\n  z-index: 1;\n}\n.was-validated .input-group .form-control:valid:focus, .input-group .form-control.is-valid:focus,\n.was-validated .input-group .form-select:valid:focus,\n.input-group .form-select.is-valid:focus {\n  z-index: 3;\n}\n\n.invalid-feedback {\n  display: none;\n  width: 100%;\n  margin-top: 0.25rem;\n  font-size: 0.875em;\n  color: #dc3545;\n}\n\n.invalid-tooltip {\n  position: absolute;\n  top: 100%;\n  z-index: 5;\n  display: none;\n  max-width: 100%;\n  padding: 0.25rem 0.5rem;\n  margin-top: 0.1rem;\n  font-size: 0.875rem;\n  color: #fff;\n  background-color: rgba(220, 53, 69, 0.9);\n  border-radius: 0.25rem;\n}\n\n.was-validated :invalid ~ .invalid-feedback,\n.was-validated :invalid ~ .invalid-tooltip,\n.is-invalid ~ .invalid-feedback,\n.is-invalid ~ .invalid-tooltip {\n  display: block;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid {\n  border-color: #dc3545;\n  padding-right: calc(1.5em + 0.75rem);\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e\");\n  background-repeat: no-repeat;\n  background-position: right calc(0.375em + 0.1875rem) center;\n  background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {\n  border-color: #dc3545;\n  box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {\n  padding-right: calc(1.5em + 0.75rem);\n  background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);\n}\n\n.was-validated .form-select:invalid, .form-select.is-invalid {\n  border-color: #dc3545;\n}\n.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size=\"1\"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size=\"1\"] {\n  padding-right: 4.125rem;\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e\"), url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e\");\n  background-position: right 0.75rem center, center right 2.25rem;\n  background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);\n}\n.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus {\n  border-color: #dc3545;\n  box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-check-input:invalid, .form-check-input.is-invalid {\n  border-color: #dc3545;\n}\n.was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked {\n  background-color: #dc3545;\n}\n.was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus {\n  box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25);\n}\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n  color: #dc3545;\n}\n\n.form-check-inline .form-check-input ~ .invalid-feedback {\n  margin-left: 0.5em;\n}\n\n.was-validated .input-group .form-control:invalid, .input-group .form-control.is-invalid,\n.was-validated .input-group .form-select:invalid,\n.input-group .form-select.is-invalid {\n  z-index: 2;\n}\n.was-validated .input-group .form-control:invalid:focus, .input-group .form-control.is-invalid:focus,\n.was-validated .input-group .form-select:invalid:focus,\n.input-group .form-select.is-invalid:focus {\n  z-index: 3;\n}\n\n.btn {\n  display: inline-block;\n  font-weight: 400;\n  line-height: 1.5;\n  color: #212529;\n  text-align: center;\n  text-decoration: none;\n  vertical-align: middle;\n  cursor: pointer;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n  background-color: transparent;\n  border: 1px solid transparent;\n  padding: 0.375rem 0.75rem;\n  font-size: 1rem;\n  border-radius: 0.25rem;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .btn {\n    transition: none;\n  }\n}\n.btn:hover {\n  color: #212529;\n}\n.btn-check:focus + .btn, .btn:focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n.btn:disabled, .btn.disabled, fieldset:disabled .btn {\n  pointer-events: none;\n  opacity: 0.65;\n}\n\n.btn-primary {\n  color: #fff;\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n.btn-primary:hover {\n  color: #fff;\n  background-color: #0b5ed7;\n  border-color: #0a58ca;\n}\n.btn-check:focus + .btn-primary, .btn-primary:focus {\n  color: #fff;\n  background-color: #0b5ed7;\n  border-color: #0a58ca;\n  box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5);\n}\n.btn-check:checked + .btn-primary, .btn-check:active + .btn-primary, .btn-primary:active, .btn-primary.active, .show > .btn-primary.dropdown-toggle {\n  color: #fff;\n  background-color: #0a58ca;\n  border-color: #0a53be;\n}\n.btn-check:checked + .btn-primary:focus, .btn-check:active + .btn-primary:focus, .btn-primary:active:focus, .btn-primary.active:focus, .show > .btn-primary.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5);\n}\n.btn-primary:disabled, .btn-primary.disabled {\n  color: #fff;\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n\n.btn-secondary {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n.btn-secondary:hover {\n  color: #fff;\n  background-color: #5c636a;\n  border-color: #565e64;\n}\n.btn-check:focus + .btn-secondary, .btn-secondary:focus {\n  color: #fff;\n  background-color: #5c636a;\n  border-color: #565e64;\n  box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5);\n}\n.btn-check:checked + .btn-secondary, .btn-check:active + .btn-secondary, .btn-secondary:active, .btn-secondary.active, .show > .btn-secondary.dropdown-toggle {\n  color: #fff;\n  background-color: #565e64;\n  border-color: #51585e;\n}\n.btn-check:checked + .btn-secondary:focus, .btn-check:active + .btn-secondary:focus, .btn-secondary:active:focus, .btn-secondary.active:focus, .show > .btn-secondary.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5);\n}\n.btn-secondary:disabled, .btn-secondary.disabled {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n\n.btn-success {\n  color: #fff;\n  background-color: #198754;\n  border-color: #198754;\n}\n.btn-success:hover {\n  color: #fff;\n  background-color: #157347;\n  border-color: #146c43;\n}\n.btn-check:focus + .btn-success, .btn-success:focus {\n  color: #fff;\n  background-color: #157347;\n  border-color: #146c43;\n  box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5);\n}\n.btn-check:checked + .btn-success, .btn-check:active + .btn-success, .btn-success:active, .btn-success.active, .show > .btn-success.dropdown-toggle {\n  color: #fff;\n  background-color: #146c43;\n  border-color: #13653f;\n}\n.btn-check:checked + .btn-success:focus, .btn-check:active + .btn-success:focus, .btn-success:active:focus, .btn-success.active:focus, .show > .btn-success.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5);\n}\n.btn-success:disabled, .btn-success.disabled {\n  color: #fff;\n  background-color: #198754;\n  border-color: #198754;\n}\n\n.btn-info {\n  color: #000;\n  background-color: #0dcaf0;\n  border-color: #0dcaf0;\n}\n.btn-info:hover {\n  color: #000;\n  background-color: #31d2f2;\n  border-color: #25cff2;\n}\n.btn-check:focus + .btn-info, .btn-info:focus {\n  color: #000;\n  background-color: #31d2f2;\n  border-color: #25cff2;\n  box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5);\n}\n.btn-check:checked + .btn-info, .btn-check:active + .btn-info, .btn-info:active, .btn-info.active, .show > .btn-info.dropdown-toggle {\n  color: #000;\n  background-color: #3dd5f3;\n  border-color: #25cff2;\n}\n.btn-check:checked + .btn-info:focus, .btn-check:active + .btn-info:focus, .btn-info:active:focus, .btn-info.active:focus, .show > .btn-info.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5);\n}\n.btn-info:disabled, .btn-info.disabled {\n  color: #000;\n  background-color: #0dcaf0;\n  border-color: #0dcaf0;\n}\n\n.btn-warning {\n  color: #000;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n.btn-warning:hover {\n  color: #000;\n  background-color: #ffca2c;\n  border-color: #ffc720;\n}\n.btn-check:focus + .btn-warning, .btn-warning:focus {\n  color: #000;\n  background-color: #ffca2c;\n  border-color: #ffc720;\n  box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5);\n}\n.btn-check:checked + .btn-warning, .btn-check:active + .btn-warning, .btn-warning:active, .btn-warning.active, .show > .btn-warning.dropdown-toggle {\n  color: #000;\n  background-color: #ffcd39;\n  border-color: #ffc720;\n}\n.btn-check:checked + .btn-warning:focus, .btn-check:active + .btn-warning:focus, .btn-warning:active:focus, .btn-warning.active:focus, .show > .btn-warning.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5);\n}\n.btn-warning:disabled, .btn-warning.disabled {\n  color: #000;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n\n.btn-danger {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n.btn-danger:hover {\n  color: #fff;\n  background-color: #bb2d3b;\n  border-color: #b02a37;\n}\n.btn-check:focus + .btn-danger, .btn-danger:focus {\n  color: #fff;\n  background-color: #bb2d3b;\n  border-color: #b02a37;\n  box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5);\n}\n.btn-check:checked + .btn-danger, .btn-check:active + .btn-danger, .btn-danger:active, .btn-danger.active, .show > .btn-danger.dropdown-toggle {\n  color: #fff;\n  background-color: #b02a37;\n  border-color: #a52834;\n}\n.btn-check:checked + .btn-danger:focus, .btn-check:active + .btn-danger:focus, .btn-danger:active:focus, .btn-danger.active:focus, .show > .btn-danger.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5);\n}\n.btn-danger:disabled, .btn-danger.disabled {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n\n.btn-light {\n  color: #000;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n.btn-light:hover {\n  color: #000;\n  background-color: #f9fafb;\n  border-color: #f9fafb;\n}\n.btn-check:focus + .btn-light, .btn-light:focus {\n  color: #000;\n  background-color: #f9fafb;\n  border-color: #f9fafb;\n  box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5);\n}\n.btn-check:checked + .btn-light, .btn-check:active + .btn-light, .btn-light:active, .btn-light.active, .show > .btn-light.dropdown-toggle {\n  color: #000;\n  background-color: #f9fafb;\n  border-color: #f9fafb;\n}\n.btn-check:checked + .btn-light:focus, .btn-check:active + .btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show > .btn-light.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5);\n}\n.btn-light:disabled, .btn-light.disabled {\n  color: #000;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n\n.btn-dark {\n  color: #fff;\n  background-color: #212529;\n  border-color: #212529;\n}\n.btn-dark:hover {\n  color: #fff;\n  background-color: #1c1f23;\n  border-color: #1a1e21;\n}\n.btn-check:focus + .btn-dark, .btn-dark:focus {\n  color: #fff;\n  background-color: #1c1f23;\n  border-color: #1a1e21;\n  box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5);\n}\n.btn-check:checked + .btn-dark, .btn-check:active + .btn-dark, .btn-dark:active, .btn-dark.active, .show > .btn-dark.dropdown-toggle {\n  color: #fff;\n  background-color: #1a1e21;\n  border-color: #191c1f;\n}\n.btn-check:checked + .btn-dark:focus, .btn-check:active + .btn-dark:focus, .btn-dark:active:focus, .btn-dark.active:focus, .show > .btn-dark.dropdown-toggle:focus {\n  box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5);\n}\n.btn-dark:disabled, .btn-dark.disabled {\n  color: #fff;\n  background-color: #212529;\n  border-color: #212529;\n}\n\n.btn-outline-primary {\n  color: #0d6efd;\n  border-color: #0d6efd;\n}\n.btn-outline-primary:hover {\n  color: #fff;\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n.btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus {\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5);\n}\n.btn-check:checked + .btn-outline-primary, .btn-check:active + .btn-outline-primary, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary.dropdown-toggle.show {\n  color: #fff;\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n.btn-check:checked + .btn-outline-primary:focus, .btn-check:active + .btn-outline-primary:focus, .btn-outline-primary:active:focus, .btn-outline-primary.active:focus, .btn-outline-primary.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5);\n}\n.btn-outline-primary:disabled, .btn-outline-primary.disabled {\n  color: #0d6efd;\n  background-color: transparent;\n}\n\n.btn-outline-secondary {\n  color: #6c757d;\n  border-color: #6c757d;\n}\n.btn-outline-secondary:hover {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n.btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus {\n  box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5);\n}\n.btn-check:checked + .btn-outline-secondary, .btn-check:active + .btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show {\n  color: #fff;\n  background-color: #6c757d;\n  border-color: #6c757d;\n}\n.btn-check:checked + .btn-outline-secondary:focus, .btn-check:active + .btn-outline-secondary:focus, .btn-outline-secondary:active:focus, .btn-outline-secondary.active:focus, .btn-outline-secondary.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5);\n}\n.btn-outline-secondary:disabled, .btn-outline-secondary.disabled {\n  color: #6c757d;\n  background-color: transparent;\n}\n\n.btn-outline-success {\n  color: #198754;\n  border-color: #198754;\n}\n.btn-outline-success:hover {\n  color: #fff;\n  background-color: #198754;\n  border-color: #198754;\n}\n.btn-check:focus + .btn-outline-success, .btn-outline-success:focus {\n  box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5);\n}\n.btn-check:checked + .btn-outline-success, .btn-check:active + .btn-outline-success, .btn-outline-success:active, .btn-outline-success.active, .btn-outline-success.dropdown-toggle.show {\n  color: #fff;\n  background-color: #198754;\n  border-color: #198754;\n}\n.btn-check:checked + .btn-outline-success:focus, .btn-check:active + .btn-outline-success:focus, .btn-outline-success:active:focus, .btn-outline-success.active:focus, .btn-outline-success.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5);\n}\n.btn-outline-success:disabled, .btn-outline-success.disabled {\n  color: #198754;\n  background-color: transparent;\n}\n\n.btn-outline-info {\n  color: #0dcaf0;\n  border-color: #0dcaf0;\n}\n.btn-outline-info:hover {\n  color: #000;\n  background-color: #0dcaf0;\n  border-color: #0dcaf0;\n}\n.btn-check:focus + .btn-outline-info, .btn-outline-info:focus {\n  box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5);\n}\n.btn-check:checked + .btn-outline-info, .btn-check:active + .btn-outline-info, .btn-outline-info:active, .btn-outline-info.active, .btn-outline-info.dropdown-toggle.show {\n  color: #000;\n  background-color: #0dcaf0;\n  border-color: #0dcaf0;\n}\n.btn-check:checked + .btn-outline-info:focus, .btn-check:active + .btn-outline-info:focus, .btn-outline-info:active:focus, .btn-outline-info.active:focus, .btn-outline-info.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5);\n}\n.btn-outline-info:disabled, .btn-outline-info.disabled {\n  color: #0dcaf0;\n  background-color: transparent;\n}\n\n.btn-outline-warning {\n  color: #ffc107;\n  border-color: #ffc107;\n}\n.btn-outline-warning:hover {\n  color: #000;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n.btn-check:focus + .btn-outline-warning, .btn-outline-warning:focus {\n  box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5);\n}\n.btn-check:checked + .btn-outline-warning, .btn-check:active + .btn-outline-warning, .btn-outline-warning:active, .btn-outline-warning.active, .btn-outline-warning.dropdown-toggle.show {\n  color: #000;\n  background-color: #ffc107;\n  border-color: #ffc107;\n}\n.btn-check:checked + .btn-outline-warning:focus, .btn-check:active + .btn-outline-warning:focus, .btn-outline-warning:active:focus, .btn-outline-warning.active:focus, .btn-outline-warning.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5);\n}\n.btn-outline-warning:disabled, .btn-outline-warning.disabled {\n  color: #ffc107;\n  background-color: transparent;\n}\n\n.btn-outline-danger {\n  color: #dc3545;\n  border-color: #dc3545;\n}\n.btn-outline-danger:hover {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n.btn-check:focus + .btn-outline-danger, .btn-outline-danger:focus {\n  box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5);\n}\n.btn-check:checked + .btn-outline-danger, .btn-check:active + .btn-outline-danger, .btn-outline-danger:active, .btn-outline-danger.active, .btn-outline-danger.dropdown-toggle.show {\n  color: #fff;\n  background-color: #dc3545;\n  border-color: #dc3545;\n}\n.btn-check:checked + .btn-outline-danger:focus, .btn-check:active + .btn-outline-danger:focus, .btn-outline-danger:active:focus, .btn-outline-danger.active:focus, .btn-outline-danger.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5);\n}\n.btn-outline-danger:disabled, .btn-outline-danger.disabled {\n  color: #dc3545;\n  background-color: transparent;\n}\n\n.btn-outline-light {\n  color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n.btn-outline-light:hover {\n  color: #000;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n.btn-check:focus + .btn-outline-light, .btn-outline-light:focus {\n  box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5);\n}\n.btn-check:checked + .btn-outline-light, .btn-check:active + .btn-outline-light, .btn-outline-light:active, .btn-outline-light.active, .btn-outline-light.dropdown-toggle.show {\n  color: #000;\n  background-color: #f8f9fa;\n  border-color: #f8f9fa;\n}\n.btn-check:checked + .btn-outline-light:focus, .btn-check:active + .btn-outline-light:focus, .btn-outline-light:active:focus, .btn-outline-light.active:focus, .btn-outline-light.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5);\n}\n.btn-outline-light:disabled, .btn-outline-light.disabled {\n  color: #f8f9fa;\n  background-color: transparent;\n}\n\n.btn-outline-dark {\n  color: #212529;\n  border-color: #212529;\n}\n.btn-outline-dark:hover {\n  color: #fff;\n  background-color: #212529;\n  border-color: #212529;\n}\n.btn-check:focus + .btn-outline-dark, .btn-outline-dark:focus {\n  box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5);\n}\n.btn-check:checked + .btn-outline-dark, .btn-check:active + .btn-outline-dark, .btn-outline-dark:active, .btn-outline-dark.active, .btn-outline-dark.dropdown-toggle.show {\n  color: #fff;\n  background-color: #212529;\n  border-color: #212529;\n}\n.btn-check:checked + .btn-outline-dark:focus, .btn-check:active + .btn-outline-dark:focus, .btn-outline-dark:active:focus, .btn-outline-dark.active:focus, .btn-outline-dark.dropdown-toggle.show:focus {\n  box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5);\n}\n.btn-outline-dark:disabled, .btn-outline-dark.disabled {\n  color: #212529;\n  background-color: transparent;\n}\n\n.btn-link {\n  font-weight: 400;\n  color: #0d6efd;\n  text-decoration: underline;\n}\n.btn-link:hover {\n  color: #0a58ca;\n}\n.btn-link:disabled, .btn-link.disabled {\n  color: #6c757d;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n  padding: 0.5rem 1rem;\n  font-size: 1.25rem;\n  border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n  border-radius: 0.2rem;\n}\n\n.fade {\n  transition: opacity 0.15s linear;\n}\n@media (prefers-reduced-motion: reduce) {\n  .fade {\n    transition: none;\n  }\n}\n.fade:not(.show) {\n  opacity: 0;\n}\n\n.collapse:not(.show) {\n  display: none;\n}\n\n.collapsing {\n  height: 0;\n  overflow: hidden;\n  transition: height 0.35s ease;\n}\n@media (prefers-reduced-motion: reduce) {\n  .collapsing {\n    transition: none;\n  }\n}\n\n.dropup,\n.dropend,\n.dropdown,\n.dropstart {\n  position: relative;\n}\n\n.dropdown-toggle {\n  white-space: nowrap;\n}\n.dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0;\n  border-left: 0.3em solid transparent;\n}\n.dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropdown-menu {\n  position: absolute;\n  z-index: 1000;\n  display: none;\n  min-width: 10rem;\n  padding: 0.5rem 0;\n  margin: 0;\n  font-size: 1rem;\n  color: #212529;\n  text-align: left;\n  list-style: none;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 0.25rem;\n}\n.dropdown-menu[data-bs-popper] {\n  top: 100%;\n  left: 0;\n  margin-top: 0.125rem;\n}\n\n.dropdown-menu-start {\n  --bs-position: start;\n}\n.dropdown-menu-start[data-bs-popper] {\n  right: auto;\n  left: 0;\n}\n\n.dropdown-menu-end {\n  --bs-position: end;\n}\n.dropdown-menu-end[data-bs-popper] {\n  right: 0;\n  left: auto;\n}\n\n@media (min-width: 576px) {\n  .dropdown-menu-sm-start {\n    --bs-position: start;\n  }\n  .dropdown-menu-sm-start[data-bs-popper] {\n    right: auto;\n    left: 0;\n  }\n\n  .dropdown-menu-sm-end {\n    --bs-position: end;\n  }\n  .dropdown-menu-sm-end[data-bs-popper] {\n    right: 0;\n    left: auto;\n  }\n}\n@media (min-width: 768px) {\n  .dropdown-menu-md-start {\n    --bs-position: start;\n  }\n  .dropdown-menu-md-start[data-bs-popper] {\n    right: auto;\n    left: 0;\n  }\n\n  .dropdown-menu-md-end {\n    --bs-position: end;\n  }\n  .dropdown-menu-md-end[data-bs-popper] {\n    right: 0;\n    left: auto;\n  }\n}\n@media (min-width: 992px) {\n  .dropdown-menu-lg-start {\n    --bs-position: start;\n  }\n  .dropdown-menu-lg-start[data-bs-popper] {\n    right: auto;\n    left: 0;\n  }\n\n  .dropdown-menu-lg-end {\n    --bs-position: end;\n  }\n  .dropdown-menu-lg-end[data-bs-popper] {\n    right: 0;\n    left: auto;\n  }\n}\n@media (min-width: 1200px) {\n  .dropdown-menu-xl-start {\n    --bs-position: start;\n  }\n  .dropdown-menu-xl-start[data-bs-popper] {\n    right: auto;\n    left: 0;\n  }\n\n  .dropdown-menu-xl-end {\n    --bs-position: end;\n  }\n  .dropdown-menu-xl-end[data-bs-popper] {\n    right: 0;\n    left: auto;\n  }\n}\n@media (min-width: 1400px) {\n  .dropdown-menu-xxl-start {\n    --bs-position: start;\n  }\n  .dropdown-menu-xxl-start[data-bs-popper] {\n    right: auto;\n    left: 0;\n  }\n\n  .dropdown-menu-xxl-end {\n    --bs-position: end;\n  }\n  .dropdown-menu-xxl-end[data-bs-popper] {\n    right: 0;\n    left: auto;\n  }\n}\n.dropup .dropdown-menu[data-bs-popper] {\n  top: auto;\n  bottom: 100%;\n  margin-top: 0;\n  margin-bottom: 0.125rem;\n}\n.dropup .dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0;\n  border-right: 0.3em solid transparent;\n  border-bottom: 0.3em solid;\n  border-left: 0.3em solid transparent;\n}\n.dropup .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n\n.dropend .dropdown-menu[data-bs-popper] {\n  top: 0;\n  right: auto;\n  left: 100%;\n  margin-top: 0;\n  margin-left: 0.125rem;\n}\n.dropend .dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid transparent;\n  border-right: 0;\n  border-bottom: 0.3em solid transparent;\n  border-left: 0.3em solid;\n}\n.dropend .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n.dropend .dropdown-toggle::after {\n  vertical-align: 0;\n}\n\n.dropstart .dropdown-menu[data-bs-popper] {\n  top: 0;\n  right: 100%;\n  left: auto;\n  margin-top: 0;\n  margin-right: 0.125rem;\n}\n.dropstart .dropdown-toggle::after {\n  display: inline-block;\n  margin-left: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n}\n.dropstart .dropdown-toggle::after {\n  display: none;\n}\n.dropstart .dropdown-toggle::before {\n  display: inline-block;\n  margin-right: 0.255em;\n  vertical-align: 0.255em;\n  content: \"\";\n  border-top: 0.3em solid transparent;\n  border-right: 0.3em solid;\n  border-bottom: 0.3em solid transparent;\n}\n.dropstart .dropdown-toggle:empty::after {\n  margin-left: 0;\n}\n.dropstart .dropdown-toggle::before {\n  vertical-align: 0;\n}\n\n.dropdown-divider {\n  height: 0;\n  margin: 0.5rem 0;\n  overflow: hidden;\n  border-top: 1px solid rgba(0, 0, 0, 0.15);\n}\n\n.dropdown-item {\n  display: block;\n  width: 100%;\n  padding: 0.25rem 1rem;\n  clear: both;\n  font-weight: 400;\n  color: #212529;\n  text-align: inherit;\n  text-decoration: none;\n  white-space: nowrap;\n  background-color: transparent;\n  border: 0;\n}\n.dropdown-item:hover, .dropdown-item:focus {\n  color: #1e2125;\n  background-color: #e9ecef;\n}\n.dropdown-item.active, .dropdown-item:active {\n  color: #fff;\n  text-decoration: none;\n  background-color: #0d6efd;\n}\n.dropdown-item.disabled, .dropdown-item:disabled {\n  color: #adb5bd;\n  pointer-events: none;\n  background-color: transparent;\n}\n\n.dropdown-menu.show {\n  display: block;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 0.5rem 1rem;\n  margin-bottom: 0;\n  font-size: 0.875rem;\n  color: #6c757d;\n  white-space: nowrap;\n}\n\n.dropdown-item-text {\n  display: block;\n  padding: 0.25rem 1rem;\n  color: #212529;\n}\n\n.dropdown-menu-dark {\n  color: #dee2e6;\n  background-color: #343a40;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n.dropdown-menu-dark .dropdown-item {\n  color: #dee2e6;\n}\n.dropdown-menu-dark .dropdown-item:hover, .dropdown-menu-dark .dropdown-item:focus {\n  color: #fff;\n  background-color: rgba(255, 255, 255, 0.15);\n}\n.dropdown-menu-dark .dropdown-item.active, .dropdown-menu-dark .dropdown-item:active {\n  color: #fff;\n  background-color: #0d6efd;\n}\n.dropdown-menu-dark .dropdown-item.disabled, .dropdown-menu-dark .dropdown-item:disabled {\n  color: #adb5bd;\n}\n.dropdown-menu-dark .dropdown-divider {\n  border-color: rgba(0, 0, 0, 0.15);\n}\n.dropdown-menu-dark .dropdown-item-text {\n  color: #dee2e6;\n}\n.dropdown-menu-dark .dropdown-header {\n  color: #adb5bd;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-flex;\n  vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  flex: 1 1 auto;\n}\n.btn-group > .btn-check:checked + .btn,\n.btn-group > .btn-check:focus + .btn,\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn-check:checked + .btn,\n.btn-group-vertical > .btn-check:focus + .btn,\n.btn-group-vertical > .btn:hover,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n  z-index: 1;\n}\n\n.btn-toolbar {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: flex-start;\n}\n.btn-toolbar .input-group {\n  width: auto;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) {\n  margin-left: -1px;\n}\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.btn-group > .btn:nth-child(n+3),\n.btn-group > :not(.btn-check) + .btn,\n.btn-group > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.dropdown-toggle-split {\n  padding-right: 0.5625rem;\n  padding-left: 0.5625rem;\n}\n.dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after {\n  margin-left: 0;\n}\n.dropstart .dropdown-toggle-split::before {\n  margin-right: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n  padding-right: 0.375rem;\n  padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n  padding-right: 0.75rem;\n  padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n  flex-direction: column;\n  align-items: flex-start;\n  justify-content: center;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n  width: 100%;\n}\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) {\n  margin-top: -1px;\n}\n.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group-vertical > .btn-group:not(:last-child) > .btn {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn ~ .btn,\n.btn-group-vertical > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.nav {\n  display: flex;\n  flex-wrap: wrap;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav-link {\n  display: block;\n  padding: 0.5rem 1rem;\n  color: #0d6efd;\n  text-decoration: none;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .nav-link {\n    transition: none;\n  }\n}\n.nav-link:hover, .nav-link:focus {\n  color: #0a58ca;\n}\n.nav-link.disabled {\n  color: #6c757d;\n  pointer-events: none;\n  cursor: default;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dee2e6;\n}\n.nav-tabs .nav-link {\n  margin-bottom: -1px;\n  background: none;\n  border: 1px solid transparent;\n  border-top-left-radius: 0.25rem;\n  border-top-right-radius: 0.25rem;\n}\n.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n  border-color: #e9ecef #e9ecef #dee2e6;\n  isolation: isolate;\n}\n.nav-tabs .nav-link.disabled {\n  color: #6c757d;\n  background-color: transparent;\n  border-color: transparent;\n}\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n  color: #495057;\n  background-color: #fff;\n  border-color: #dee2e6 #dee2e6 #fff;\n}\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n  background: none;\n  border: 0;\n  border-radius: 0.25rem;\n}\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n  color: #fff;\n  background-color: #0d6efd;\n}\n\n.nav-fill > .nav-link,\n.nav-fill .nav-item {\n  flex: 1 1 auto;\n  text-align: center;\n}\n\n.nav-justified > .nav-link,\n.nav-justified .nav-item {\n  flex-basis: 0;\n  flex-grow: 1;\n  text-align: center;\n}\n\n.nav-fill .nav-item .nav-link,\n.nav-justified .nav-item .nav-link {\n  width: 100%;\n}\n\n.tab-content > .tab-pane {\n  display: none;\n}\n.tab-content > .active {\n  display: block;\n}\n\n.navbar {\n  position: relative;\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  justify-content: space-between;\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n.navbar > .container,\n.navbar > .container-fluid,\n.navbar > .container-sm,\n.navbar > .container-md,\n.navbar > .container-lg,\n.navbar > .container-xl,\n.navbar > .container-xxl {\n  display: flex;\n  flex-wrap: inherit;\n  align-items: center;\n  justify-content: space-between;\n}\n.navbar-brand {\n  padding-top: 0.3125rem;\n  padding-bottom: 0.3125rem;\n  margin-right: 1rem;\n  font-size: 1.25rem;\n  text-decoration: none;\n  white-space: nowrap;\n}\n.navbar-nav {\n  display: flex;\n  flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n.navbar-nav .nav-link {\n  padding-right: 0;\n  padding-left: 0;\n}\n.navbar-nav .dropdown-menu {\n  position: static;\n}\n\n.navbar-text {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n  flex-basis: 100%;\n  flex-grow: 1;\n  align-items: center;\n}\n\n.navbar-toggler {\n  padding: 0.25rem 0.75rem;\n  font-size: 1.25rem;\n  line-height: 1;\n  background-color: transparent;\n  border: 1px solid transparent;\n  border-radius: 0.25rem;\n  transition: box-shadow 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .navbar-toggler {\n    transition: none;\n  }\n}\n.navbar-toggler:hover {\n  text-decoration: none;\n}\n.navbar-toggler:focus {\n  text-decoration: none;\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem;\n}\n\n.navbar-toggler-icon {\n  display: inline-block;\n  width: 1.5em;\n  height: 1.5em;\n  vertical-align: middle;\n  background-repeat: no-repeat;\n  background-position: center;\n  background-size: 100%;\n}\n\n.navbar-nav-scroll {\n  max-height: var(--bs-scroll-height, 75vh);\n  overflow-y: auto;\n}\n\n@media (min-width: 576px) {\n  .navbar-expand-sm {\n    flex-wrap: nowrap;\n    justify-content: flex-start;\n  }\n  .navbar-expand-sm .navbar-nav {\n    flex-direction: row;\n  }\n  .navbar-expand-sm .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-sm .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-sm .navbar-nav-scroll {\n    overflow: visible;\n  }\n  .navbar-expand-sm .navbar-collapse {\n    display: flex !important;\n    flex-basis: auto;\n  }\n  .navbar-expand-sm .navbar-toggler {\n    display: none;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-expand-md {\n    flex-wrap: nowrap;\n    justify-content: flex-start;\n  }\n  .navbar-expand-md .navbar-nav {\n    flex-direction: row;\n  }\n  .navbar-expand-md .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-md .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-md .navbar-nav-scroll {\n    overflow: visible;\n  }\n  .navbar-expand-md .navbar-collapse {\n    display: flex !important;\n    flex-basis: auto;\n  }\n  .navbar-expand-md .navbar-toggler {\n    display: none;\n  }\n}\n@media (min-width: 992px) {\n  .navbar-expand-lg {\n    flex-wrap: nowrap;\n    justify-content: flex-start;\n  }\n  .navbar-expand-lg .navbar-nav {\n    flex-direction: row;\n  }\n  .navbar-expand-lg .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-lg .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-lg .navbar-nav-scroll {\n    overflow: visible;\n  }\n  .navbar-expand-lg .navbar-collapse {\n    display: flex !important;\n    flex-basis: auto;\n  }\n  .navbar-expand-lg .navbar-toggler {\n    display: none;\n  }\n}\n@media (min-width: 1200px) {\n  .navbar-expand-xl {\n    flex-wrap: nowrap;\n    justify-content: flex-start;\n  }\n  .navbar-expand-xl .navbar-nav {\n    flex-direction: row;\n  }\n  .navbar-expand-xl .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-xl .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-xl .navbar-nav-scroll {\n    overflow: visible;\n  }\n  .navbar-expand-xl .navbar-collapse {\n    display: flex !important;\n    flex-basis: auto;\n  }\n  .navbar-expand-xl .navbar-toggler {\n    display: none;\n  }\n}\n@media (min-width: 1400px) {\n  .navbar-expand-xxl {\n    flex-wrap: nowrap;\n    justify-content: flex-start;\n  }\n  .navbar-expand-xxl .navbar-nav {\n    flex-direction: row;\n  }\n  .navbar-expand-xxl .navbar-nav .dropdown-menu {\n    position: absolute;\n  }\n  .navbar-expand-xxl .navbar-nav .nav-link {\n    padding-right: 0.5rem;\n    padding-left: 0.5rem;\n  }\n  .navbar-expand-xxl .navbar-nav-scroll {\n    overflow: visible;\n  }\n  .navbar-expand-xxl .navbar-collapse {\n    display: flex !important;\n    flex-basis: auto;\n  }\n  .navbar-expand-xxl .navbar-toggler {\n    display: none;\n  }\n}\n.navbar-expand {\n  flex-wrap: nowrap;\n  justify-content: flex-start;\n}\n.navbar-expand .navbar-nav {\n  flex-direction: row;\n}\n.navbar-expand .navbar-nav .dropdown-menu {\n  position: absolute;\n}\n.navbar-expand .navbar-nav .nav-link {\n  padding-right: 0.5rem;\n  padding-left: 0.5rem;\n}\n.navbar-expand .navbar-nav-scroll {\n  overflow: visible;\n}\n.navbar-expand .navbar-collapse {\n  display: flex !important;\n  flex-basis: auto;\n}\n.navbar-expand .navbar-toggler {\n  display: none;\n}\n\n.navbar-light .navbar-brand {\n  color: rgba(0, 0, 0, 0.9);\n}\n.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n  color: rgba(0, 0, 0, 0.9);\n}\n.navbar-light .navbar-nav .nav-link {\n  color: rgba(0, 0, 0, 0.55);\n}\n.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n  color: rgba(0, 0, 0, 0.7);\n}\n.navbar-light .navbar-nav .nav-link.disabled {\n  color: rgba(0, 0, 0, 0.3);\n}\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .nav-link.active {\n  color: rgba(0, 0, 0, 0.9);\n}\n.navbar-light .navbar-toggler {\n  color: rgba(0, 0, 0, 0.55);\n  border-color: rgba(0, 0, 0, 0.1);\n}\n.navbar-light .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n.navbar-light .navbar-text {\n  color: rgba(0, 0, 0, 0.55);\n}\n.navbar-light .navbar-text a,\n.navbar-light .navbar-text a:hover,\n.navbar-light .navbar-text a:focus {\n  color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n  color: #fff;\n}\n.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n  color: #fff;\n}\n.navbar-dark .navbar-nav .nav-link {\n  color: rgba(255, 255, 255, 0.55);\n}\n.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n  color: rgba(255, 255, 255, 0.75);\n}\n.navbar-dark .navbar-nav .nav-link.disabled {\n  color: rgba(255, 255, 255, 0.25);\n}\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .nav-link.active {\n  color: #fff;\n}\n.navbar-dark .navbar-toggler {\n  color: rgba(255, 255, 255, 0.55);\n  border-color: rgba(255, 255, 255, 0.1);\n}\n.navbar-dark .navbar-toggler-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");\n}\n.navbar-dark .navbar-text {\n  color: rgba(255, 255, 255, 0.55);\n}\n.navbar-dark .navbar-text a,\n.navbar-dark .navbar-text a:hover,\n.navbar-dark .navbar-text a:focus {\n  color: #fff;\n}\n\n.card {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  min-width: 0;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: border-box;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n  border-radius: 0.25rem;\n}\n.card > hr {\n  margin-right: 0;\n  margin-left: 0;\n}\n.card > .list-group {\n  border-top: inherit;\n  border-bottom: inherit;\n}\n.card > .list-group:first-child {\n  border-top-width: 0;\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n.card > .list-group:last-child {\n  border-bottom-width: 0;\n  border-bottom-right-radius: calc(0.25rem - 1px);\n  border-bottom-left-radius: calc(0.25rem - 1px);\n}\n.card > .card-header + .list-group,\n.card > .list-group + .card-footer {\n  border-top: 0;\n}\n\n.card-body {\n  flex: 1 1 auto;\n  padding: 1rem 1rem;\n}\n\n.card-title {\n  margin-bottom: 0.5rem;\n}\n\n.card-subtitle {\n  margin-top: -0.25rem;\n  margin-bottom: 0;\n}\n\n.card-text:last-child {\n  margin-bottom: 0;\n}\n\n.card-link:hover {\n  text-decoration: none;\n}\n.card-link + .card-link {\n  margin-left: 1rem;\n}\n\n.card-header {\n  padding: 0.5rem 1rem;\n  margin-bottom: 0;\n  background-color: rgba(0, 0, 0, 0.03);\n  border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n.card-header:first-child {\n  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-footer {\n  padding: 0.5rem 1rem;\n  background-color: rgba(0, 0, 0, 0.03);\n  border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n.card-footer:last-child {\n  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n  margin-right: -0.5rem;\n  margin-bottom: -0.5rem;\n  margin-left: -0.5rem;\n  border-bottom: 0;\n}\n\n.card-header-pills {\n  margin-right: -0.5rem;\n  margin-left: -0.5rem;\n}\n\n.card-img-overlay {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: 1rem;\n  border-radius: calc(0.25rem - 1px);\n}\n\n.card-img,\n.card-img-top,\n.card-img-bottom {\n  width: 100%;\n}\n\n.card-img,\n.card-img-top {\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img,\n.card-img-bottom {\n  border-bottom-right-radius: calc(0.25rem - 1px);\n  border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-group > .card {\n  margin-bottom: 0.75rem;\n}\n@media (min-width: 576px) {\n  .card-group {\n    display: flex;\n    flex-flow: row wrap;\n  }\n  .card-group > .card {\n    flex: 1 0 0%;\n    margin-bottom: 0;\n  }\n  .card-group > .card + .card {\n    margin-left: 0;\n    border-left: 0;\n  }\n  .card-group > .card:not(:last-child) {\n    border-top-right-radius: 0;\n    border-bottom-right-radius: 0;\n  }\n  .card-group > .card:not(:last-child) .card-img-top,\n.card-group > .card:not(:last-child) .card-header {\n    border-top-right-radius: 0;\n  }\n  .card-group > .card:not(:last-child) .card-img-bottom,\n.card-group > .card:not(:last-child) .card-footer {\n    border-bottom-right-radius: 0;\n  }\n  .card-group > .card:not(:first-child) {\n    border-top-left-radius: 0;\n    border-bottom-left-radius: 0;\n  }\n  .card-group > .card:not(:first-child) .card-img-top,\n.card-group > .card:not(:first-child) .card-header {\n    border-top-left-radius: 0;\n  }\n  .card-group > .card:not(:first-child) .card-img-bottom,\n.card-group > .card:not(:first-child) .card-footer {\n    border-bottom-left-radius: 0;\n  }\n}\n\n.accordion-button {\n  position: relative;\n  display: flex;\n  align-items: center;\n  width: 100%;\n  padding: 1rem 1.25rem;\n  font-size: 1rem;\n  color: #212529;\n  text-align: left;\n  background-color: #fff;\n  border: 0;\n  border-radius: 0;\n  overflow-anchor: none;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;\n}\n@media (prefers-reduced-motion: reduce) {\n  .accordion-button {\n    transition: none;\n  }\n}\n.accordion-button:not(.collapsed) {\n  color: #0c63e4;\n  background-color: #e7f1ff;\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125);\n}\n.accordion-button:not(.collapsed)::after {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e\");\n  transform: rotate(-180deg);\n}\n.accordion-button::after {\n  flex-shrink: 0;\n  width: 1.25rem;\n  height: 1.25rem;\n  margin-left: auto;\n  content: \"\";\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e\");\n  background-repeat: no-repeat;\n  background-size: 1.25rem;\n  transition: transform 0.2s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .accordion-button::after {\n    transition: none;\n  }\n}\n.accordion-button:hover {\n  z-index: 2;\n}\n.accordion-button:focus {\n  z-index: 3;\n  border-color: #86b7fe;\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n\n.accordion-header {\n  margin-bottom: 0;\n}\n\n.accordion-item {\n  background-color: #fff;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n}\n.accordion-item:first-of-type {\n  border-top-left-radius: 0.25rem;\n  border-top-right-radius: 0.25rem;\n}\n.accordion-item:first-of-type .accordion-button {\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n.accordion-item:not(:first-of-type) {\n  border-top: 0;\n}\n.accordion-item:last-of-type {\n  border-bottom-right-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n.accordion-item:last-of-type .accordion-button.collapsed {\n  border-bottom-right-radius: calc(0.25rem - 1px);\n  border-bottom-left-radius: calc(0.25rem - 1px);\n}\n.accordion-item:last-of-type .accordion-collapse {\n  border-bottom-right-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n\n.accordion-body {\n  padding: 1rem 1.25rem;\n}\n\n.accordion-flush .accordion-collapse {\n  border-width: 0;\n}\n.accordion-flush .accordion-item {\n  border-right: 0;\n  border-left: 0;\n  border-radius: 0;\n}\n.accordion-flush .accordion-item:first-child {\n  border-top: 0;\n}\n.accordion-flush .accordion-item:last-child {\n  border-bottom: 0;\n}\n.accordion-flush .accordion-item .accordion-button {\n  border-radius: 0;\n}\n\n.breadcrumb {\n  display: flex;\n  flex-wrap: wrap;\n  padding: 0 0;\n  margin-bottom: 1rem;\n  list-style: none;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n  padding-left: 0.5rem;\n}\n.breadcrumb-item + .breadcrumb-item::before {\n  float: left;\n  padding-right: 0.5rem;\n  color: #6c757d;\n  content: var(--bs-breadcrumb-divider, \"/\") /* rtl: var(--bs-breadcrumb-divider, \"/\") */;\n}\n.breadcrumb-item.active {\n  color: #6c757d;\n}\n\n.pagination {\n  display: flex;\n  padding-left: 0;\n  list-style: none;\n}\n\n.page-link {\n  position: relative;\n  display: block;\n  color: #0d6efd;\n  text-decoration: none;\n  background-color: #fff;\n  border: 1px solid #dee2e6;\n  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .page-link {\n    transition: none;\n  }\n}\n.page-link:hover {\n  z-index: 2;\n  color: #0a58ca;\n  background-color: #e9ecef;\n  border-color: #dee2e6;\n}\n.page-link:focus {\n  z-index: 3;\n  color: #0a58ca;\n  background-color: #e9ecef;\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n}\n\n.page-item:not(:first-child) .page-link {\n  margin-left: -1px;\n}\n.page-item.active .page-link {\n  z-index: 3;\n  color: #fff;\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n.page-item.disabled .page-link {\n  color: #6c757d;\n  pointer-events: none;\n  background-color: #fff;\n  border-color: #dee2e6;\n}\n\n.page-link {\n  padding: 0.375rem 0.75rem;\n}\n\n.page-item:first-child .page-link {\n  border-top-left-radius: 0.25rem;\n  border-bottom-left-radius: 0.25rem;\n}\n.page-item:last-child .page-link {\n  border-top-right-radius: 0.25rem;\n  border-bottom-right-radius: 0.25rem;\n}\n\n.pagination-lg .page-link {\n  padding: 0.75rem 1.5rem;\n  font-size: 1.25rem;\n}\n.pagination-lg .page-item:first-child .page-link {\n  border-top-left-radius: 0.3rem;\n  border-bottom-left-radius: 0.3rem;\n}\n.pagination-lg .page-item:last-child .page-link {\n  border-top-right-radius: 0.3rem;\n  border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n  padding: 0.25rem 0.5rem;\n  font-size: 0.875rem;\n}\n.pagination-sm .page-item:first-child .page-link {\n  border-top-left-radius: 0.2rem;\n  border-bottom-left-radius: 0.2rem;\n}\n.pagination-sm .page-item:last-child .page-link {\n  border-top-right-radius: 0.2rem;\n  border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n  display: inline-block;\n  padding: 0.35em 0.65em;\n  font-size: 0.75em;\n  font-weight: 700;\n  line-height: 1;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: 0.25rem;\n}\n.badge:empty {\n  display: none;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n.alert {\n  position: relative;\n  padding: 1rem 1rem;\n  margin-bottom: 1rem;\n  border: 1px solid transparent;\n  border-radius: 0.25rem;\n}\n\n.alert-heading {\n  color: inherit;\n}\n\n.alert-link {\n  font-weight: 700;\n}\n\n.alert-dismissible {\n  padding-right: 3rem;\n}\n.alert-dismissible .btn-close {\n  position: absolute;\n  top: 0;\n  right: 0;\n  z-index: 2;\n  padding: 1.25rem 1rem;\n}\n\n.alert-primary {\n  color: #084298;\n  background-color: #cfe2ff;\n  border-color: #b6d4fe;\n}\n.alert-primary .alert-link {\n  color: #06357a;\n}\n\n.alert-secondary {\n  color: #41464b;\n  background-color: #e2e3e5;\n  border-color: #d3d6d8;\n}\n.alert-secondary .alert-link {\n  color: #34383c;\n}\n\n.alert-success {\n  color: #0f5132;\n  background-color: #d1e7dd;\n  border-color: #badbcc;\n}\n.alert-success .alert-link {\n  color: #0c4128;\n}\n\n.alert-info {\n  color: #055160;\n  background-color: #cff4fc;\n  border-color: #b6effb;\n}\n.alert-info .alert-link {\n  color: #04414d;\n}\n\n.alert-warning {\n  color: #664d03;\n  background-color: #fff3cd;\n  border-color: #ffecb5;\n}\n.alert-warning .alert-link {\n  color: #523e02;\n}\n\n.alert-danger {\n  color: #842029;\n  background-color: #f8d7da;\n  border-color: #f5c2c7;\n}\n.alert-danger .alert-link {\n  color: #6a1a21;\n}\n\n.alert-light {\n  color: #636464;\n  background-color: #fefefe;\n  border-color: #fdfdfe;\n}\n.alert-light .alert-link {\n  color: #4f5050;\n}\n\n.alert-dark {\n  color: #141619;\n  background-color: #d3d3d4;\n  border-color: #bcbebf;\n}\n.alert-dark .alert-link {\n  color: #101214;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  0% {\n    background-position-x: 1rem;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  0% {\n    background-position-x: 1rem;\n  }\n}\n.progress {\n  display: flex;\n  height: 1rem;\n  overflow: hidden;\n  font-size: 0.75rem;\n  background-color: #e9ecef;\n  border-radius: 0.25rem;\n}\n\n.progress-bar {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  overflow: hidden;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  background-color: #0d6efd;\n  transition: width 0.6s ease;\n}\n@media (prefers-reduced-motion: reduce) {\n  .progress-bar {\n    transition: none;\n  }\n}\n\n.progress-bar-striped {\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 1rem 1rem;\n}\n\n.progress-bar-animated {\n  -webkit-animation: 1s linear infinite progress-bar-stripes;\n  animation: 1s linear infinite progress-bar-stripes;\n}\n@media (prefers-reduced-motion: reduce) {\n  .progress-bar-animated {\n    -webkit-animation: none;\n    animation: none;\n  }\n}\n\n.list-group {\n  display: flex;\n  flex-direction: column;\n  padding-left: 0;\n  margin-bottom: 0;\n  border-radius: 0.25rem;\n}\n\n.list-group-numbered {\n  list-style-type: none;\n  counter-reset: section;\n}\n.list-group-numbered > li::before {\n  content: counters(section, \".\") \". \";\n  counter-increment: section;\n}\n\n.list-group-item-action {\n  width: 100%;\n  color: #495057;\n  text-align: inherit;\n}\n.list-group-item-action:hover, .list-group-item-action:focus {\n  z-index: 1;\n  color: #495057;\n  text-decoration: none;\n  background-color: #f8f9fa;\n}\n.list-group-item-action:active {\n  color: #212529;\n  background-color: #e9ecef;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 0.5rem 1rem;\n  color: #212529;\n  text-decoration: none;\n  background-color: #fff;\n  border: 1px solid rgba(0, 0, 0, 0.125);\n}\n.list-group-item:first-child {\n  border-top-left-radius: inherit;\n  border-top-right-radius: inherit;\n}\n.list-group-item:last-child {\n  border-bottom-right-radius: inherit;\n  border-bottom-left-radius: inherit;\n}\n.list-group-item.disabled, .list-group-item:disabled {\n  color: #6c757d;\n  pointer-events: none;\n  background-color: #fff;\n}\n.list-group-item.active {\n  z-index: 2;\n  color: #fff;\n  background-color: #0d6efd;\n  border-color: #0d6efd;\n}\n.list-group-item + .list-group-item {\n  border-top-width: 0;\n}\n.list-group-item + .list-group-item.active {\n  margin-top: -1px;\n  border-top-width: 1px;\n}\n\n.list-group-horizontal {\n  flex-direction: row;\n}\n.list-group-horizontal > .list-group-item:first-child {\n  border-bottom-left-radius: 0.25rem;\n  border-top-right-radius: 0;\n}\n.list-group-horizontal > .list-group-item:last-child {\n  border-top-right-radius: 0.25rem;\n  border-bottom-left-radius: 0;\n}\n.list-group-horizontal > .list-group-item.active {\n  margin-top: 0;\n}\n.list-group-horizontal > .list-group-item + .list-group-item {\n  border-top-width: 1px;\n  border-left-width: 0;\n}\n.list-group-horizontal > .list-group-item + .list-group-item.active {\n  margin-left: -1px;\n  border-left-width: 1px;\n}\n\n@media (min-width: 576px) {\n  .list-group-horizontal-sm {\n    flex-direction: row;\n  }\n  .list-group-horizontal-sm > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-sm > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n@media (min-width: 768px) {\n  .list-group-horizontal-md {\n    flex-direction: row;\n  }\n  .list-group-horizontal-md > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-md > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-md > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-md > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-md > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n@media (min-width: 992px) {\n  .list-group-horizontal-lg {\n    flex-direction: row;\n  }\n  .list-group-horizontal-lg > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-lg > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n@media (min-width: 1200px) {\n  .list-group-horizontal-xl {\n    flex-direction: row;\n  }\n  .list-group-horizontal-xl > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-xl > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n@media (min-width: 1400px) {\n  .list-group-horizontal-xxl {\n    flex-direction: row;\n  }\n  .list-group-horizontal-xxl > .list-group-item:first-child {\n    border-bottom-left-radius: 0.25rem;\n    border-top-right-radius: 0;\n  }\n  .list-group-horizontal-xxl > .list-group-item:last-child {\n    border-top-right-radius: 0.25rem;\n    border-bottom-left-radius: 0;\n  }\n  .list-group-horizontal-xxl > .list-group-item.active {\n    margin-top: 0;\n  }\n  .list-group-horizontal-xxl > .list-group-item + .list-group-item {\n    border-top-width: 1px;\n    border-left-width: 0;\n  }\n  .list-group-horizontal-xxl > .list-group-item + .list-group-item.active {\n    margin-left: -1px;\n    border-left-width: 1px;\n  }\n}\n.list-group-flush {\n  border-radius: 0;\n}\n.list-group-flush > .list-group-item {\n  border-width: 0 0 1px;\n}\n.list-group-flush > .list-group-item:last-child {\n  border-bottom-width: 0;\n}\n\n.list-group-item-primary {\n  color: #084298;\n  background-color: #cfe2ff;\n}\n.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n  color: #084298;\n  background-color: #bacbe6;\n}\n.list-group-item-primary.list-group-item-action.active {\n  color: #fff;\n  background-color: #084298;\n  border-color: #084298;\n}\n\n.list-group-item-secondary {\n  color: #41464b;\n  background-color: #e2e3e5;\n}\n.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n  color: #41464b;\n  background-color: #cbccce;\n}\n.list-group-item-secondary.list-group-item-action.active {\n  color: #fff;\n  background-color: #41464b;\n  border-color: #41464b;\n}\n\n.list-group-item-success {\n  color: #0f5132;\n  background-color: #d1e7dd;\n}\n.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n  color: #0f5132;\n  background-color: #bcd0c7;\n}\n.list-group-item-success.list-group-item-action.active {\n  color: #fff;\n  background-color: #0f5132;\n  border-color: #0f5132;\n}\n\n.list-group-item-info {\n  color: #055160;\n  background-color: #cff4fc;\n}\n.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n  color: #055160;\n  background-color: #badce3;\n}\n.list-group-item-info.list-group-item-action.active {\n  color: #fff;\n  background-color: #055160;\n  border-color: #055160;\n}\n\n.list-group-item-warning {\n  color: #664d03;\n  background-color: #fff3cd;\n}\n.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n  color: #664d03;\n  background-color: #e6dbb9;\n}\n.list-group-item-warning.list-group-item-action.active {\n  color: #fff;\n  background-color: #664d03;\n  border-color: #664d03;\n}\n\n.list-group-item-danger {\n  color: #842029;\n  background-color: #f8d7da;\n}\n.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n  color: #842029;\n  background-color: #dfc2c4;\n}\n.list-group-item-danger.list-group-item-action.active {\n  color: #fff;\n  background-color: #842029;\n  border-color: #842029;\n}\n\n.list-group-item-light {\n  color: #636464;\n  background-color: #fefefe;\n}\n.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n  color: #636464;\n  background-color: #e5e5e5;\n}\n.list-group-item-light.list-group-item-action.active {\n  color: #fff;\n  background-color: #636464;\n  border-color: #636464;\n}\n\n.list-group-item-dark {\n  color: #141619;\n  background-color: #d3d3d4;\n}\n.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n  color: #141619;\n  background-color: #bebebf;\n}\n.list-group-item-dark.list-group-item-action.active {\n  color: #fff;\n  background-color: #141619;\n  border-color: #141619;\n}\n\n.btn-close {\n  box-sizing: content-box;\n  width: 1em;\n  height: 1em;\n  padding: 0.25em 0.25em;\n  color: #000;\n  background: transparent url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e\") center/1em auto no-repeat;\n  border: 0;\n  border-radius: 0.25rem;\n  opacity: 0.5;\n}\n.btn-close:hover {\n  color: #000;\n  text-decoration: none;\n  opacity: 0.75;\n}\n.btn-close:focus {\n  outline: 0;\n  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n  opacity: 1;\n}\n.btn-close:disabled, .btn-close.disabled {\n  pointer-events: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n  opacity: 0.25;\n}\n\n.btn-close-white {\n  filter: invert(1) grayscale(100%) brightness(200%);\n}\n\n.toast {\n  width: 350px;\n  max-width: 100%;\n  font-size: 0.875rem;\n  pointer-events: auto;\n  background-color: rgba(255, 255, 255, 0.85);\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);\n  border-radius: 0.25rem;\n}\n.toast:not(.showing):not(.show) {\n  opacity: 0;\n}\n.toast.hide {\n  display: none;\n}\n\n.toast-container {\n  width: -webkit-max-content;\n  width: -moz-max-content;\n  width: max-content;\n  max-width: 100%;\n  pointer-events: none;\n}\n.toast-container > :not(:last-child) {\n  margin-bottom: 0.75rem;\n}\n\n.toast-header {\n  display: flex;\n  align-items: center;\n  padding: 0.5rem 0.75rem;\n  color: #6c757d;\n  background-color: rgba(255, 255, 255, 0.85);\n  background-clip: padding-box;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n  border-top-left-radius: calc(0.25rem - 1px);\n  border-top-right-radius: calc(0.25rem - 1px);\n}\n.toast-header .btn-close {\n  margin-right: -0.375rem;\n  margin-left: 0.75rem;\n}\n\n.toast-body {\n  padding: 0.75rem;\n  word-wrap: break-word;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 1060;\n  display: none;\n  width: 100%;\n  height: 100%;\n  overflow-x: hidden;\n  overflow-y: auto;\n  outline: 0;\n}\n\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 0.5rem;\n  pointer-events: none;\n}\n.modal.fade .modal-dialog {\n  transition: transform 0.3s ease-out;\n  transform: translate(0, -50px);\n}\n@media (prefers-reduced-motion: reduce) {\n  .modal.fade .modal-dialog {\n    transition: none;\n  }\n}\n.modal.show .modal-dialog {\n  transform: none;\n}\n.modal.modal-static .modal-dialog {\n  transform: scale(1.02);\n}\n\n.modal-dialog-scrollable {\n  height: calc(100% - 1rem);\n}\n.modal-dialog-scrollable .modal-content {\n  max-height: 100%;\n  overflow: hidden;\n}\n.modal-dialog-scrollable .modal-body {\n  overflow-y: auto;\n}\n\n.modal-dialog-centered {\n  display: flex;\n  align-items: center;\n  min-height: calc(100% - 1rem);\n}\n\n.modal-content {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n  pointer-events: auto;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 0.3rem;\n  outline: 0;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 1040;\n  width: 100vw;\n  height: 100vh;\n  background-color: #000;\n}\n.modal-backdrop.fade {\n  opacity: 0;\n}\n.modal-backdrop.show {\n  opacity: 0.5;\n}\n\n.modal-header {\n  display: flex;\n  flex-shrink: 0;\n  align-items: center;\n  justify-content: space-between;\n  padding: 1rem 1rem;\n  border-bottom: 1px solid #dee2e6;\n  border-top-left-radius: calc(0.3rem - 1px);\n  border-top-right-radius: calc(0.3rem - 1px);\n}\n.modal-header .btn-close {\n  padding: 0.5rem 0.5rem;\n  margin: -0.5rem -0.5rem -0.5rem auto;\n}\n\n.modal-title {\n  margin-bottom: 0;\n  line-height: 1.5;\n}\n\n.modal-body {\n  position: relative;\n  flex: 1 1 auto;\n  padding: 1rem;\n}\n\n.modal-footer {\n  display: flex;\n  flex-wrap: wrap;\n  flex-shrink: 0;\n  align-items: center;\n  justify-content: flex-end;\n  padding: 0.75rem;\n  border-top: 1px solid #dee2e6;\n  border-bottom-right-radius: calc(0.3rem - 1px);\n  border-bottom-left-radius: calc(0.3rem - 1px);\n}\n.modal-footer > * {\n  margin: 0.25rem;\n}\n\n@media (min-width: 576px) {\n  .modal-dialog {\n    max-width: 500px;\n    margin: 1.75rem auto;\n  }\n\n  .modal-dialog-scrollable {\n    height: calc(100% - 3.5rem);\n  }\n\n  .modal-dialog-centered {\n    min-height: calc(100% - 3.5rem);\n  }\n\n  .modal-sm {\n    max-width: 300px;\n  }\n}\n@media (min-width: 992px) {\n  .modal-lg,\n.modal-xl {\n    max-width: 800px;\n  }\n}\n@media (min-width: 1200px) {\n  .modal-xl {\n    max-width: 1140px;\n  }\n}\n.modal-fullscreen {\n  width: 100vw;\n  max-width: none;\n  height: 100%;\n  margin: 0;\n}\n.modal-fullscreen .modal-content {\n  height: 100%;\n  border: 0;\n  border-radius: 0;\n}\n.modal-fullscreen .modal-header {\n  border-radius: 0;\n}\n.modal-fullscreen .modal-body {\n  overflow-y: auto;\n}\n.modal-fullscreen .modal-footer {\n  border-radius: 0;\n}\n\n@media (max-width: 575.98px) {\n  .modal-fullscreen-sm-down {\n    width: 100vw;\n    max-width: none;\n    height: 100%;\n    margin: 0;\n  }\n  .modal-fullscreen-sm-down .modal-content {\n    height: 100%;\n    border: 0;\n    border-radius: 0;\n  }\n  .modal-fullscreen-sm-down .modal-header {\n    border-radius: 0;\n  }\n  .modal-fullscreen-sm-down .modal-body {\n    overflow-y: auto;\n  }\n  .modal-fullscreen-sm-down .modal-footer {\n    border-radius: 0;\n  }\n}\n@media (max-width: 767.98px) {\n  .modal-fullscreen-md-down {\n    width: 100vw;\n    max-width: none;\n    height: 100%;\n    margin: 0;\n  }\n  .modal-fullscreen-md-down .modal-content {\n    height: 100%;\n    border: 0;\n    border-radius: 0;\n  }\n  .modal-fullscreen-md-down .modal-header {\n    border-radius: 0;\n  }\n  .modal-fullscreen-md-down .modal-body {\n    overflow-y: auto;\n  }\n  .modal-fullscreen-md-down .modal-footer {\n    border-radius: 0;\n  }\n}\n@media (max-width: 991.98px) {\n  .modal-fullscreen-lg-down {\n    width: 100vw;\n    max-width: none;\n    height: 100%;\n    margin: 0;\n  }\n  .modal-fullscreen-lg-down .modal-content {\n    height: 100%;\n    border: 0;\n    border-radius: 0;\n  }\n  .modal-fullscreen-lg-down .modal-header {\n    border-radius: 0;\n  }\n  .modal-fullscreen-lg-down .modal-body {\n    overflow-y: auto;\n  }\n  .modal-fullscreen-lg-down .modal-footer {\n    border-radius: 0;\n  }\n}\n@media (max-width: 1199.98px) {\n  .modal-fullscreen-xl-down {\n    width: 100vw;\n    max-width: none;\n    height: 100%;\n    margin: 0;\n  }\n  .modal-fullscreen-xl-down .modal-content {\n    height: 100%;\n    border: 0;\n    border-radius: 0;\n  }\n  .modal-fullscreen-xl-down .modal-header {\n    border-radius: 0;\n  }\n  .modal-fullscreen-xl-down .modal-body {\n    overflow-y: auto;\n  }\n  .modal-fullscreen-xl-down .modal-footer {\n    border-radius: 0;\n  }\n}\n@media (max-width: 1399.98px) {\n  .modal-fullscreen-xxl-down {\n    width: 100vw;\n    max-width: none;\n    height: 100%;\n    margin: 0;\n  }\n  .modal-fullscreen-xxl-down .modal-content {\n    height: 100%;\n    border: 0;\n    border-radius: 0;\n  }\n  .modal-fullscreen-xxl-down .modal-header {\n    border-radius: 0;\n  }\n  .modal-fullscreen-xxl-down .modal-body {\n    overflow-y: auto;\n  }\n  .modal-fullscreen-xxl-down .modal-footer {\n    border-radius: 0;\n  }\n}\n.tooltip {\n  position: absolute;\n  z-index: 1080;\n  display: block;\n  margin: 0;\n  font-family: var(--bs-font-sans-serif);\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.875rem;\n  word-wrap: break-word;\n  opacity: 0;\n}\n.tooltip.show {\n  opacity: 0.9;\n}\n.tooltip .tooltip-arrow {\n  position: absolute;\n  display: block;\n  width: 0.8rem;\n  height: 0.4rem;\n}\n.tooltip .tooltip-arrow::before {\n  position: absolute;\n  content: \"\";\n  border-color: transparent;\n  border-style: solid;\n}\n\n.bs-tooltip-top, .bs-tooltip-auto[data-popper-placement^=top] {\n  padding: 0.4rem 0;\n}\n.bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow {\n  bottom: 0;\n}\n.bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before {\n  top: -1px;\n  border-width: 0.4rem 0.4rem 0;\n  border-top-color: #000;\n}\n\n.bs-tooltip-end, .bs-tooltip-auto[data-popper-placement^=right] {\n  padding: 0 0.4rem;\n}\n.bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow {\n  left: 0;\n  width: 0.4rem;\n  height: 0.8rem;\n}\n.bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before {\n  right: -1px;\n  border-width: 0.4rem 0.4rem 0.4rem 0;\n  border-right-color: #000;\n}\n\n.bs-tooltip-bottom, .bs-tooltip-auto[data-popper-placement^=bottom] {\n  padding: 0.4rem 0;\n}\n.bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow {\n  top: 0;\n}\n.bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before {\n  bottom: -1px;\n  border-width: 0 0.4rem 0.4rem;\n  border-bottom-color: #000;\n}\n\n.bs-tooltip-start, .bs-tooltip-auto[data-popper-placement^=left] {\n  padding: 0 0.4rem;\n}\n.bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow {\n  right: 0;\n  width: 0.4rem;\n  height: 0.8rem;\n}\n.bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before {\n  left: -1px;\n  border-width: 0.4rem 0 0.4rem 0.4rem;\n  border-left-color: #000;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 0.25rem 0.5rem;\n  color: #fff;\n  text-align: center;\n  background-color: #000;\n  border-radius: 0.25rem;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0 /* rtl:ignore */;\n  z-index: 1070;\n  display: block;\n  max-width: 276px;\n  font-family: var(--bs-font-sans-serif);\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.5;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  white-space: normal;\n  line-break: auto;\n  font-size: 0.875rem;\n  word-wrap: break-word;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 0.3rem;\n}\n.popover .popover-arrow {\n  position: absolute;\n  display: block;\n  width: 1rem;\n  height: 0.5rem;\n}\n.popover .popover-arrow::before, .popover .popover-arrow::after {\n  position: absolute;\n  display: block;\n  content: \"\";\n  border-color: transparent;\n  border-style: solid;\n}\n\n.bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow {\n  bottom: calc(-0.5rem - 1px);\n}\n.bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before {\n  bottom: 0;\n  border-width: 0.5rem 0.5rem 0;\n  border-top-color: rgba(0, 0, 0, 0.25);\n}\n.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after {\n  bottom: 1px;\n  border-width: 0.5rem 0.5rem 0;\n  border-top-color: #fff;\n}\n\n.bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow {\n  left: calc(-0.5rem - 1px);\n  width: 0.5rem;\n  height: 1rem;\n}\n.bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before {\n  left: 0;\n  border-width: 0.5rem 0.5rem 0.5rem 0;\n  border-right-color: rgba(0, 0, 0, 0.25);\n}\n.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after {\n  left: 1px;\n  border-width: 0.5rem 0.5rem 0.5rem 0;\n  border-right-color: #fff;\n}\n\n.bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow {\n  top: calc(-0.5rem - 1px);\n}\n.bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before {\n  top: 0;\n  border-width: 0 0.5rem 0.5rem 0.5rem;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after {\n  top: 1px;\n  border-width: 0 0.5rem 0.5rem 0.5rem;\n  border-bottom-color: #fff;\n}\n.bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  display: block;\n  width: 1rem;\n  margin-left: -0.5rem;\n  content: \"\";\n  border-bottom: 1px solid #f0f0f0;\n}\n\n.bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow {\n  right: calc(-0.5rem - 1px);\n  width: 0.5rem;\n  height: 1rem;\n}\n.bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before {\n  right: 0;\n  border-width: 0.5rem 0 0.5rem 0.5rem;\n  border-left-color: rgba(0, 0, 0, 0.25);\n}\n.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after {\n  right: 1px;\n  border-width: 0.5rem 0 0.5rem 0.5rem;\n  border-left-color: #fff;\n}\n\n.popover-header {\n  padding: 0.5rem 1rem;\n  margin-bottom: 0;\n  font-size: 1rem;\n  background-color: #f0f0f0;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n  border-top-left-radius: calc(0.3rem - 1px);\n  border-top-right-radius: calc(0.3rem - 1px);\n}\n.popover-header:empty {\n  display: none;\n}\n\n.popover-body {\n  padding: 1rem 1rem;\n  color: #212529;\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel.pointer-event {\n  touch-action: pan-y;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n.carousel-inner::after {\n  display: block;\n  clear: both;\n  content: \"\";\n}\n\n.carousel-item {\n  position: relative;\n  display: none;\n  float: left;\n  width: 100%;\n  margin-right: -100%;\n  -webkit-backface-visibility: hidden;\n  backface-visibility: hidden;\n  transition: transform 0.6s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .carousel-item {\n    transition: none;\n  }\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n  display: block;\n}\n\n/* rtl:begin:ignore */\n.carousel-item-next:not(.carousel-item-start),\n.active.carousel-item-end {\n  transform: translateX(100%);\n}\n\n.carousel-item-prev:not(.carousel-item-end),\n.active.carousel-item-start {\n  transform: translateX(-100%);\n}\n\n/* rtl:end:ignore */\n.carousel-fade .carousel-item {\n  opacity: 0;\n  transition-property: opacity;\n  transform: none;\n}\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-start,\n.carousel-fade .carousel-item-prev.carousel-item-end {\n  z-index: 1;\n  opacity: 1;\n}\n.carousel-fade .active.carousel-item-start,\n.carousel-fade .active.carousel-item-end {\n  z-index: 0;\n  opacity: 0;\n  transition: opacity 0s 0.6s;\n}\n@media (prefers-reduced-motion: reduce) {\n  .carousel-fade .active.carousel-item-start,\n.carousel-fade .active.carousel-item-end {\n    transition: none;\n  }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  z-index: 1;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 15%;\n  padding: 0;\n  color: #fff;\n  text-align: center;\n  background: none;\n  border: 0;\n  opacity: 0.5;\n  transition: opacity 0.15s ease;\n}\n@media (prefers-reduced-motion: reduce) {\n  .carousel-control-prev,\n.carousel-control-next {\n    transition: none;\n  }\n}\n.carousel-control-prev:hover, .carousel-control-prev:focus,\n.carousel-control-next:hover,\n.carousel-control-next:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  opacity: 0.9;\n}\n\n.carousel-control-prev {\n  left: 0;\n}\n\n.carousel-control-next {\n  right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n  display: inline-block;\n  width: 2rem;\n  height: 2rem;\n  background-repeat: no-repeat;\n  background-position: 50%;\n  background-size: 100% 100%;\n}\n\n/* rtl:options: {\n  \"autoRename\": true,\n  \"stringMap\":[ {\n    \"name\"    : \"prev-next\",\n    \"search\"  : \"prev\",\n    \"replace\" : \"next\"\n  } ]\n} */\n.carousel-control-prev-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e\");\n}\n\n.carousel-control-next-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e\");\n}\n\n.carousel-indicators {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 2;\n  display: flex;\n  justify-content: center;\n  padding: 0;\n  margin-right: 15%;\n  margin-bottom: 1rem;\n  margin-left: 15%;\n  list-style: none;\n}\n.carousel-indicators [data-bs-target] {\n  box-sizing: content-box;\n  flex: 0 1 auto;\n  width: 30px;\n  height: 3px;\n  padding: 0;\n  margin-right: 3px;\n  margin-left: 3px;\n  text-indent: -999px;\n  cursor: pointer;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 0;\n  border-top: 10px solid transparent;\n  border-bottom: 10px solid transparent;\n  opacity: 0.5;\n  transition: opacity 0.6s ease;\n}\n@media (prefers-reduced-motion: reduce) {\n  .carousel-indicators [data-bs-target] {\n    transition: none;\n  }\n}\n.carousel-indicators .active {\n  opacity: 1;\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 15%;\n  bottom: 1.25rem;\n  left: 15%;\n  padding-top: 1.25rem;\n  padding-bottom: 1.25rem;\n  color: #fff;\n  text-align: center;\n}\n\n.carousel-dark .carousel-control-prev-icon,\n.carousel-dark .carousel-control-next-icon {\n  filter: invert(1) grayscale(100);\n}\n.carousel-dark .carousel-indicators [data-bs-target] {\n  background-color: #000;\n}\n.carousel-dark .carousel-caption {\n  color: #000;\n}\n\n@-webkit-keyframes spinner-border {\n  to {\n    transform: rotate(360deg) /* rtl:ignore */;\n  }\n}\n\n@keyframes spinner-border {\n  to {\n    transform: rotate(360deg) /* rtl:ignore */;\n  }\n}\n.spinner-border {\n  display: inline-block;\n  width: 2rem;\n  height: 2rem;\n  vertical-align: -0.125em;\n  border: 0.25em solid currentColor;\n  border-right-color: transparent;\n  border-radius: 50%;\n  -webkit-animation: 0.75s linear infinite spinner-border;\n  animation: 0.75s linear infinite spinner-border;\n}\n\n.spinner-border-sm {\n  width: 1rem;\n  height: 1rem;\n  border-width: 0.2em;\n}\n\n@-webkit-keyframes spinner-grow {\n  0% {\n    transform: scale(0);\n  }\n  50% {\n    opacity: 1;\n    transform: none;\n  }\n}\n\n@keyframes spinner-grow {\n  0% {\n    transform: scale(0);\n  }\n  50% {\n    opacity: 1;\n    transform: none;\n  }\n}\n.spinner-grow {\n  display: inline-block;\n  width: 2rem;\n  height: 2rem;\n  vertical-align: -0.125em;\n  background-color: currentColor;\n  border-radius: 50%;\n  opacity: 0;\n  -webkit-animation: 0.75s linear infinite spinner-grow;\n  animation: 0.75s linear infinite spinner-grow;\n}\n\n.spinner-grow-sm {\n  width: 1rem;\n  height: 1rem;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .spinner-border,\n.spinner-grow {\n    -webkit-animation-duration: 1.5s;\n    animation-duration: 1.5s;\n  }\n}\n.offcanvas {\n  position: fixed;\n  bottom: 0;\n  z-index: 1050;\n  display: flex;\n  flex-direction: column;\n  max-width: 100%;\n  visibility: hidden;\n  background-color: #fff;\n  background-clip: padding-box;\n  outline: 0;\n  transition: transform 0.3s ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n  .offcanvas {\n    transition: none;\n  }\n}\n\n.offcanvas-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 1rem 1rem;\n}\n.offcanvas-header .btn-close {\n  padding: 0.5rem 0.5rem;\n  margin-top: -0.5rem;\n  margin-right: -0.5rem;\n  margin-bottom: -0.5rem;\n}\n\n.offcanvas-title {\n  margin-bottom: 0;\n  line-height: 1.5;\n}\n\n.offcanvas-body {\n  flex-grow: 1;\n  padding: 1rem 1rem;\n  overflow-y: auto;\n}\n\n.offcanvas-start {\n  top: 0;\n  left: 0;\n  width: 400px;\n  border-right: 1px solid rgba(0, 0, 0, 0.2);\n  transform: translateX(-100%);\n}\n\n.offcanvas-end {\n  top: 0;\n  right: 0;\n  width: 400px;\n  border-left: 1px solid rgba(0, 0, 0, 0.2);\n  transform: translateX(100%);\n}\n\n.offcanvas-top {\n  top: 0;\n  right: 0;\n  left: 0;\n  height: 30vh;\n  max-height: 100%;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n  transform: translateY(-100%);\n}\n\n.offcanvas-bottom {\n  right: 0;\n  left: 0;\n  height: 30vh;\n  max-height: 100%;\n  border-top: 1px solid rgba(0, 0, 0, 0.2);\n  transform: translateY(100%);\n}\n\n.offcanvas.show {\n  transform: none;\n}\n\n.clearfix::after {\n  display: block;\n  clear: both;\n  content: \"\";\n}\n\n.link-primary {\n  color: #0d6efd;\n}\n.link-primary:hover, .link-primary:focus {\n  color: #0a58ca;\n}\n\n.link-secondary {\n  color: #6c757d;\n}\n.link-secondary:hover, .link-secondary:focus {\n  color: #565e64;\n}\n\n.link-success {\n  color: #198754;\n}\n.link-success:hover, .link-success:focus {\n  color: #146c43;\n}\n\n.link-info {\n  color: #0dcaf0;\n}\n.link-info:hover, .link-info:focus {\n  color: #3dd5f3;\n}\n\n.link-warning {\n  color: #ffc107;\n}\n.link-warning:hover, .link-warning:focus {\n  color: #ffcd39;\n}\n\n.link-danger {\n  color: #dc3545;\n}\n.link-danger:hover, .link-danger:focus {\n  color: #b02a37;\n}\n\n.link-light {\n  color: #f8f9fa;\n}\n.link-light:hover, .link-light:focus {\n  color: #f9fafb;\n}\n\n.link-dark {\n  color: #212529;\n}\n.link-dark:hover, .link-dark:focus {\n  color: #1a1e21;\n}\n\n.ratio {\n  position: relative;\n  width: 100%;\n}\n.ratio::before {\n  display: block;\n  padding-top: var(--bs-aspect-ratio);\n  content: \"\";\n}\n.ratio > * {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n\n.ratio-1x1 {\n  --bs-aspect-ratio: 100%;\n}\n\n.ratio-4x3 {\n  --bs-aspect-ratio: calc(3 / 4 * 100%);\n}\n\n.ratio-16x9 {\n  --bs-aspect-ratio: calc(9 / 16 * 100%);\n}\n\n.ratio-21x9 {\n  --bs-aspect-ratio: calc(9 / 21 * 100%);\n}\n\n.fixed-top {\n  position: fixed;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n.fixed-bottom {\n  position: fixed;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n.sticky-top {\n  position: -webkit-sticky;\n  position: sticky;\n  top: 0;\n  z-index: 1020;\n}\n\n@media (min-width: 576px) {\n  .sticky-sm-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n@media (min-width: 768px) {\n  .sticky-md-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n@media (min-width: 992px) {\n  .sticky-lg-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n@media (min-width: 1200px) {\n  .sticky-xl-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n@media (min-width: 1400px) {\n  .sticky-xxl-top {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    z-index: 1020;\n  }\n}\n.visually-hidden,\n.visually-hidden-focusable:not(:focus):not(:focus-within) {\n  position: absolute !important;\n  width: 1px !important;\n  height: 1px !important;\n  padding: 0 !important;\n  margin: -1px !important;\n  overflow: hidden !important;\n  clip: rect(0, 0, 0, 0) !important;\n  white-space: nowrap !important;\n  border: 0 !important;\n}\n\n.stretched-link::after {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1;\n  content: \"\";\n}\n\n.text-truncate {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.align-baseline {\n  vertical-align: baseline !important;\n}\n\n.align-top {\n  vertical-align: top !important;\n}\n\n.align-middle {\n  vertical-align: middle !important;\n}\n\n.align-bottom {\n  vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n  vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n  vertical-align: text-top !important;\n}\n\n.float-start {\n  float: left !important;\n}\n\n.float-end {\n  float: right !important;\n}\n\n.float-none {\n  float: none !important;\n}\n\n.overflow-auto {\n  overflow: auto !important;\n}\n\n.overflow-hidden {\n  overflow: hidden !important;\n}\n\n.overflow-visible {\n  overflow: visible !important;\n}\n\n.overflow-scroll {\n  overflow: scroll !important;\n}\n\n.d-inline {\n  display: inline !important;\n}\n\n.d-inline-block {\n  display: inline-block !important;\n}\n\n.d-block {\n  display: block !important;\n}\n\n.d-grid {\n  display: grid !important;\n}\n\n.d-table {\n  display: table !important;\n}\n\n.d-table-row {\n  display: table-row !important;\n}\n\n.d-table-cell {\n  display: table-cell !important;\n}\n\n.d-flex {\n  display: flex !important;\n}\n\n.d-inline-flex {\n  display: inline-flex !important;\n}\n\n.d-none {\n  display: none !important;\n}\n\n.shadow {\n  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;\n}\n\n.shadow-sm {\n  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;\n}\n\n.shadow-lg {\n  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;\n}\n\n.shadow-none {\n  box-shadow: none !important;\n}\n\n.position-static {\n  position: static !important;\n}\n\n.position-relative {\n  position: relative !important;\n}\n\n.position-absolute {\n  position: absolute !important;\n}\n\n.position-fixed {\n  position: fixed !important;\n}\n\n.position-sticky {\n  position: -webkit-sticky !important;\n  position: sticky !important;\n}\n\n.top-0 {\n  top: 0 !important;\n}\n\n.top-50 {\n  top: 50% !important;\n}\n\n.top-100 {\n  top: 100% !important;\n}\n\n.bottom-0 {\n  bottom: 0 !important;\n}\n\n.bottom-50 {\n  bottom: 50% !important;\n}\n\n.bottom-100 {\n  bottom: 100% !important;\n}\n\n.start-0 {\n  left: 0 !important;\n}\n\n.start-50 {\n  left: 50% !important;\n}\n\n.start-100 {\n  left: 100% !important;\n}\n\n.end-0 {\n  right: 0 !important;\n}\n\n.end-50 {\n  right: 50% !important;\n}\n\n.end-100 {\n  right: 100% !important;\n}\n\n.translate-middle {\n  transform: translate(-50%, -50%) !important;\n}\n\n.translate-middle-x {\n  transform: translateX(-50%) !important;\n}\n\n.translate-middle-y {\n  transform: translateY(-50%) !important;\n}\n\n.border {\n  border: 1px solid #dee2e6 !important;\n}\n\n.border-0 {\n  border: 0 !important;\n}\n\n.border-top {\n  border-top: 1px solid #dee2e6 !important;\n}\n\n.border-top-0 {\n  border-top: 0 !important;\n}\n\n.border-end {\n  border-right: 1px solid #dee2e6 !important;\n}\n\n.border-end-0 {\n  border-right: 0 !important;\n}\n\n.border-bottom {\n  border-bottom: 1px solid #dee2e6 !important;\n}\n\n.border-bottom-0 {\n  border-bottom: 0 !important;\n}\n\n.border-start {\n  border-left: 1px solid #dee2e6 !important;\n}\n\n.border-start-0 {\n  border-left: 0 !important;\n}\n\n.border-primary {\n  border-color: #0d6efd !important;\n}\n\n.border-secondary {\n  border-color: #6c757d !important;\n}\n\n.border-success {\n  border-color: #198754 !important;\n}\n\n.border-info {\n  border-color: #0dcaf0 !important;\n}\n\n.border-warning {\n  border-color: #ffc107 !important;\n}\n\n.border-danger {\n  border-color: #dc3545 !important;\n}\n\n.border-light {\n  border-color: #f8f9fa !important;\n}\n\n.border-dark {\n  border-color: #212529 !important;\n}\n\n.border-white {\n  border-color: #fff !important;\n}\n\n.border-1 {\n  border-width: 1px !important;\n}\n\n.border-2 {\n  border-width: 2px !important;\n}\n\n.border-3 {\n  border-width: 3px !important;\n}\n\n.border-4 {\n  border-width: 4px !important;\n}\n\n.border-5 {\n  border-width: 5px !important;\n}\n\n.w-25 {\n  width: 25% !important;\n}\n\n.w-50 {\n  width: 50% !important;\n}\n\n.w-75 {\n  width: 75% !important;\n}\n\n.w-100 {\n  width: 100% !important;\n}\n\n.w-auto {\n  width: auto !important;\n}\n\n.mw-100 {\n  max-width: 100% !important;\n}\n\n.vw-100 {\n  width: 100vw !important;\n}\n\n.min-vw-100 {\n  min-width: 100vw !important;\n}\n\n.h-25 {\n  height: 25% !important;\n}\n\n.h-50 {\n  height: 50% !important;\n}\n\n.h-75 {\n  height: 75% !important;\n}\n\n.h-100 {\n  height: 100% !important;\n}\n\n.h-auto {\n  height: auto !important;\n}\n\n.mh-100 {\n  max-height: 100% !important;\n}\n\n.vh-100 {\n  height: 100vh !important;\n}\n\n.min-vh-100 {\n  min-height: 100vh !important;\n}\n\n.flex-fill {\n  flex: 1 1 auto !important;\n}\n\n.flex-row {\n  flex-direction: row !important;\n}\n\n.flex-column {\n  flex-direction: column !important;\n}\n\n.flex-row-reverse {\n  flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n  flex-direction: column-reverse !important;\n}\n\n.flex-grow-0 {\n  flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n  flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n  flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n  flex-shrink: 1 !important;\n}\n\n.flex-wrap {\n  flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n  flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n  flex-wrap: wrap-reverse !important;\n}\n\n.gap-0 {\n  gap: 0 !important;\n}\n\n.gap-1 {\n  gap: 0.25rem !important;\n}\n\n.gap-2 {\n  gap: 0.5rem !important;\n}\n\n.gap-3 {\n  gap: 1rem !important;\n}\n\n.gap-4 {\n  gap: 1.5rem !important;\n}\n\n.gap-5 {\n  gap: 3rem !important;\n}\n\n.justify-content-start {\n  justify-content: flex-start !important;\n}\n\n.justify-content-end {\n  justify-content: flex-end !important;\n}\n\n.justify-content-center {\n  justify-content: center !important;\n}\n\n.justify-content-between {\n  justify-content: space-between !important;\n}\n\n.justify-content-around {\n  justify-content: space-around !important;\n}\n\n.justify-content-evenly {\n  justify-content: space-evenly !important;\n}\n\n.align-items-start {\n  align-items: flex-start !important;\n}\n\n.align-items-end {\n  align-items: flex-end !important;\n}\n\n.align-items-center {\n  align-items: center !important;\n}\n\n.align-items-baseline {\n  align-items: baseline !important;\n}\n\n.align-items-stretch {\n  align-items: stretch !important;\n}\n\n.align-content-start {\n  align-content: flex-start !important;\n}\n\n.align-content-end {\n  align-content: flex-end !important;\n}\n\n.align-content-center {\n  align-content: center !important;\n}\n\n.align-content-between {\n  align-content: space-between !important;\n}\n\n.align-content-around {\n  align-content: space-around !important;\n}\n\n.align-content-stretch {\n  align-content: stretch !important;\n}\n\n.align-self-auto {\n  align-self: auto !important;\n}\n\n.align-self-start {\n  align-self: flex-start !important;\n}\n\n.align-self-end {\n  align-self: flex-end !important;\n}\n\n.align-self-center {\n  align-self: center !important;\n}\n\n.align-self-baseline {\n  align-self: baseline !important;\n}\n\n.align-self-stretch {\n  align-self: stretch !important;\n}\n\n.order-first {\n  order: -1 !important;\n}\n\n.order-0 {\n  order: 0 !important;\n}\n\n.order-1 {\n  order: 1 !important;\n}\n\n.order-2 {\n  order: 2 !important;\n}\n\n.order-3 {\n  order: 3 !important;\n}\n\n.order-4 {\n  order: 4 !important;\n}\n\n.order-5 {\n  order: 5 !important;\n}\n\n.order-last {\n  order: 6 !important;\n}\n\n.m-0 {\n  margin: 0 !important;\n}\n\n.m-1 {\n  margin: 0.25rem !important;\n}\n\n.m-2 {\n  margin: 0.5rem !important;\n}\n\n.m-3 {\n  margin: 1rem !important;\n}\n\n.m-4 {\n  margin: 1.5rem !important;\n}\n\n.m-5 {\n  margin: 3rem !important;\n}\n\n.m-auto {\n  margin: auto !important;\n}\n\n.mx-0 {\n  margin-right: 0 !important;\n  margin-left: 0 !important;\n}\n\n.mx-1 {\n  margin-right: 0.25rem !important;\n  margin-left: 0.25rem !important;\n}\n\n.mx-2 {\n  margin-right: 0.5rem !important;\n  margin-left: 0.5rem !important;\n}\n\n.mx-3 {\n  margin-right: 1rem !important;\n  margin-left: 1rem !important;\n}\n\n.mx-4 {\n  margin-right: 1.5rem !important;\n  margin-left: 1.5rem !important;\n}\n\n.mx-5 {\n  margin-right: 3rem !important;\n  margin-left: 3rem !important;\n}\n\n.mx-auto {\n  margin-right: auto !important;\n  margin-left: auto !important;\n}\n\n.my-0 {\n  margin-top: 0 !important;\n  margin-bottom: 0 !important;\n}\n\n.my-1 {\n  margin-top: 0.25rem !important;\n  margin-bottom: 0.25rem !important;\n}\n\n.my-2 {\n  margin-top: 0.5rem !important;\n  margin-bottom: 0.5rem !important;\n}\n\n.my-3 {\n  margin-top: 1rem !important;\n  margin-bottom: 1rem !important;\n}\n\n.my-4 {\n  margin-top: 1.5rem !important;\n  margin-bottom: 1.5rem !important;\n}\n\n.my-5 {\n  margin-top: 3rem !important;\n  margin-bottom: 3rem !important;\n}\n\n.my-auto {\n  margin-top: auto !important;\n  margin-bottom: auto !important;\n}\n\n.mt-0 {\n  margin-top: 0 !important;\n}\n\n.mt-1 {\n  margin-top: 0.25rem !important;\n}\n\n.mt-2 {\n  margin-top: 0.5rem !important;\n}\n\n.mt-3 {\n  margin-top: 1rem !important;\n}\n\n.mt-4 {\n  margin-top: 1.5rem !important;\n}\n\n.mt-5 {\n  margin-top: 3rem !important;\n}\n\n.mt-auto {\n  margin-top: auto !important;\n}\n\n.me-0 {\n  margin-right: 0 !important;\n}\n\n.me-1 {\n  margin-right: 0.25rem !important;\n}\n\n.me-2 {\n  margin-right: 0.5rem !important;\n}\n\n.me-3 {\n  margin-right: 1rem !important;\n}\n\n.me-4 {\n  margin-right: 1.5rem !important;\n}\n\n.me-5 {\n  margin-right: 3rem !important;\n}\n\n.me-auto {\n  margin-right: auto !important;\n}\n\n.mb-0 {\n  margin-bottom: 0 !important;\n}\n\n.mb-1 {\n  margin-bottom: 0.25rem !important;\n}\n\n.mb-2 {\n  margin-bottom: 0.5rem !important;\n}\n\n.mb-3 {\n  margin-bottom: 1rem !important;\n}\n\n.mb-4 {\n  margin-bottom: 1.5rem !important;\n}\n\n.mb-5 {\n  margin-bottom: 3rem !important;\n}\n\n.mb-auto {\n  margin-bottom: auto !important;\n}\n\n.ms-0 {\n  margin-left: 0 !important;\n}\n\n.ms-1 {\n  margin-left: 0.25rem !important;\n}\n\n.ms-2 {\n  margin-left: 0.5rem !important;\n}\n\n.ms-3 {\n  margin-left: 1rem !important;\n}\n\n.ms-4 {\n  margin-left: 1.5rem !important;\n}\n\n.ms-5 {\n  margin-left: 3rem !important;\n}\n\n.ms-auto {\n  margin-left: auto !important;\n}\n\n.p-0 {\n  padding: 0 !important;\n}\n\n.p-1 {\n  padding: 0.25rem !important;\n}\n\n.p-2 {\n  padding: 0.5rem !important;\n}\n\n.p-3 {\n  padding: 1rem !important;\n}\n\n.p-4 {\n  padding: 1.5rem !important;\n}\n\n.p-5 {\n  padding: 3rem !important;\n}\n\n.px-0 {\n  padding-right: 0 !important;\n  padding-left: 0 !important;\n}\n\n.px-1 {\n  padding-right: 0.25rem !important;\n  padding-left: 0.25rem !important;\n}\n\n.px-2 {\n  padding-right: 0.5rem !important;\n  padding-left: 0.5rem !important;\n}\n\n.px-3 {\n  padding-right: 1rem !important;\n  padding-left: 1rem !important;\n}\n\n.px-4 {\n  padding-right: 1.5rem !important;\n  padding-left: 1.5rem !important;\n}\n\n.px-5 {\n  padding-right: 3rem !important;\n  padding-left: 3rem !important;\n}\n\n.py-0 {\n  padding-top: 0 !important;\n  padding-bottom: 0 !important;\n}\n\n.py-1 {\n  padding-top: 0.25rem !important;\n  padding-bottom: 0.25rem !important;\n}\n\n.py-2 {\n  padding-top: 0.5rem !important;\n  padding-bottom: 0.5rem !important;\n}\n\n.py-3 {\n  padding-top: 1rem !important;\n  padding-bottom: 1rem !important;\n}\n\n.py-4 {\n  padding-top: 1.5rem !important;\n  padding-bottom: 1.5rem !important;\n}\n\n.py-5 {\n  padding-top: 3rem !important;\n  padding-bottom: 3rem !important;\n}\n\n.pt-0 {\n  padding-top: 0 !important;\n}\n\n.pt-1 {\n  padding-top: 0.25rem !important;\n}\n\n.pt-2 {\n  padding-top: 0.5rem !important;\n}\n\n.pt-3 {\n  padding-top: 1rem !important;\n}\n\n.pt-4 {\n  padding-top: 1.5rem !important;\n}\n\n.pt-5 {\n  padding-top: 3rem !important;\n}\n\n.pe-0 {\n  padding-right: 0 !important;\n}\n\n.pe-1 {\n  padding-right: 0.25rem !important;\n}\n\n.pe-2 {\n  padding-right: 0.5rem !important;\n}\n\n.pe-3 {\n  padding-right: 1rem !important;\n}\n\n.pe-4 {\n  padding-right: 1.5rem !important;\n}\n\n.pe-5 {\n  padding-right: 3rem !important;\n}\n\n.pb-0 {\n  padding-bottom: 0 !important;\n}\n\n.pb-1 {\n  padding-bottom: 0.25rem !important;\n}\n\n.pb-2 {\n  padding-bottom: 0.5rem !important;\n}\n\n.pb-3 {\n  padding-bottom: 1rem !important;\n}\n\n.pb-4 {\n  padding-bottom: 1.5rem !important;\n}\n\n.pb-5 {\n  padding-bottom: 3rem !important;\n}\n\n.ps-0 {\n  padding-left: 0 !important;\n}\n\n.ps-1 {\n  padding-left: 0.25rem !important;\n}\n\n.ps-2 {\n  padding-left: 0.5rem !important;\n}\n\n.ps-3 {\n  padding-left: 1rem !important;\n}\n\n.ps-4 {\n  padding-left: 1.5rem !important;\n}\n\n.ps-5 {\n  padding-left: 3rem !important;\n}\n\n.font-monospace {\n  font-family: var(--bs-font-monospace) !important;\n}\n\n.fs-1 {\n  font-size: calc(1.375rem + 1.5vw) !important;\n}\n\n.fs-2 {\n  font-size: calc(1.325rem + 0.9vw) !important;\n}\n\n.fs-3 {\n  font-size: calc(1.3rem + 0.6vw) !important;\n}\n\n.fs-4 {\n  font-size: calc(1.275rem + 0.3vw) !important;\n}\n\n.fs-5 {\n  font-size: 1.25rem !important;\n}\n\n.fs-6 {\n  font-size: 1rem !important;\n}\n\n.fst-italic {\n  font-style: italic !important;\n}\n\n.fst-normal {\n  font-style: normal !important;\n}\n\n.fw-light {\n  font-weight: 300 !important;\n}\n\n.fw-lighter {\n  font-weight: lighter !important;\n}\n\n.fw-normal {\n  font-weight: 400 !important;\n}\n\n.fw-bold {\n  font-weight: 700 !important;\n}\n\n.fw-bolder {\n  font-weight: bolder !important;\n}\n\n.lh-1 {\n  line-height: 1 !important;\n}\n\n.lh-sm {\n  line-height: 1.25 !important;\n}\n\n.lh-base {\n  line-height: 1.5 !important;\n}\n\n.lh-lg {\n  line-height: 2 !important;\n}\n\n.text-start {\n  text-align: left !important;\n}\n\n.text-end {\n  text-align: right !important;\n}\n\n.text-center {\n  text-align: center !important;\n}\n\n.text-decoration-none {\n  text-decoration: none !important;\n}\n\n.text-decoration-underline {\n  text-decoration: underline !important;\n}\n\n.text-decoration-line-through {\n  text-decoration: line-through !important;\n}\n\n.text-lowercase {\n  text-transform: lowercase !important;\n}\n\n.text-uppercase {\n  text-transform: uppercase !important;\n}\n\n.text-capitalize {\n  text-transform: capitalize !important;\n}\n\n.text-wrap {\n  white-space: normal !important;\n}\n\n.text-nowrap {\n  white-space: nowrap !important;\n}\n\n/* rtl:begin:remove */\n.text-break {\n  word-wrap: break-word !important;\n  word-break: break-word !important;\n}\n\n/* rtl:end:remove */\n.text-primary {\n  color: #0d6efd !important;\n}\n\n.text-secondary {\n  color: #6c757d !important;\n}\n\n.text-success {\n  color: #198754 !important;\n}\n\n.text-info {\n  color: #0dcaf0 !important;\n}\n\n.text-warning {\n  color: #ffc107 !important;\n}\n\n.text-danger {\n  color: #dc3545 !important;\n}\n\n.text-light {\n  color: #f8f9fa !important;\n}\n\n.text-dark {\n  color: #212529 !important;\n}\n\n.text-white {\n  color: #fff !important;\n}\n\n.text-body {\n  color: #212529 !important;\n}\n\n.text-muted {\n  color: #6c757d !important;\n}\n\n.text-black-50 {\n  color: rgba(0, 0, 0, 0.5) !important;\n}\n\n.text-white-50 {\n  color: rgba(255, 255, 255, 0.5) !important;\n}\n\n.text-reset {\n  color: inherit !important;\n}\n\n.bg-primary {\n  background-color: #0d6efd !important;\n}\n\n.bg-secondary {\n  background-color: #6c757d !important;\n}\n\n.bg-success {\n  background-color: #198754 !important;\n}\n\n.bg-info {\n  background-color: #0dcaf0 !important;\n}\n\n.bg-warning {\n  background-color: #ffc107 !important;\n}\n\n.bg-danger {\n  background-color: #dc3545 !important;\n}\n\n.bg-light {\n  background-color: #f8f9fa !important;\n}\n\n.bg-dark {\n  background-color: #212529 !important;\n}\n\n.bg-body {\n  background-color: #fff !important;\n}\n\n.bg-white {\n  background-color: #fff !important;\n}\n\n.bg-transparent {\n  background-color: transparent !important;\n}\n\n.bg-gradient {\n  background-image: var(--bs-gradient) !important;\n}\n\n.user-select-all {\n  -webkit-user-select: all !important;\n  -moz-user-select: all !important;\n  user-select: all !important;\n}\n\n.user-select-auto {\n  -webkit-user-select: auto !important;\n  -moz-user-select: auto !important;\n  user-select: auto !important;\n}\n\n.user-select-none {\n  -webkit-user-select: none !important;\n  -moz-user-select: none !important;\n  user-select: none !important;\n}\n\n.pe-none {\n  pointer-events: none !important;\n}\n\n.pe-auto {\n  pointer-events: auto !important;\n}\n\n.rounded {\n  border-radius: 0.25rem !important;\n}\n\n.rounded-0 {\n  border-radius: 0 !important;\n}\n\n.rounded-1 {\n  border-radius: 0.2rem !important;\n}\n\n.rounded-2 {\n  border-radius: 0.25rem !important;\n}\n\n.rounded-3 {\n  border-radius: 0.3rem !important;\n}\n\n.rounded-circle {\n  border-radius: 50% !important;\n}\n\n.rounded-pill {\n  border-radius: 50rem !important;\n}\n\n.rounded-top {\n  border-top-left-radius: 0.25rem !important;\n  border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-end {\n  border-top-right-radius: 0.25rem !important;\n  border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n  border-bottom-right-radius: 0.25rem !important;\n  border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-start {\n  border-bottom-left-radius: 0.25rem !important;\n  border-top-left-radius: 0.25rem !important;\n}\n\n.visible {\n  visibility: visible !important;\n}\n\n.invisible {\n  visibility: hidden !important;\n}\n\n@media (min-width: 576px) {\n  .float-sm-start {\n    float: left !important;\n  }\n\n  .float-sm-end {\n    float: right !important;\n  }\n\n  .float-sm-none {\n    float: none !important;\n  }\n\n  .d-sm-inline {\n    display: inline !important;\n  }\n\n  .d-sm-inline-block {\n    display: inline-block !important;\n  }\n\n  .d-sm-block {\n    display: block !important;\n  }\n\n  .d-sm-grid {\n    display: grid !important;\n  }\n\n  .d-sm-table {\n    display: table !important;\n  }\n\n  .d-sm-table-row {\n    display: table-row !important;\n  }\n\n  .d-sm-table-cell {\n    display: table-cell !important;\n  }\n\n  .d-sm-flex {\n    display: flex !important;\n  }\n\n  .d-sm-inline-flex {\n    display: inline-flex !important;\n  }\n\n  .d-sm-none {\n    display: none !important;\n  }\n\n  .flex-sm-fill {\n    flex: 1 1 auto !important;\n  }\n\n  .flex-sm-row {\n    flex-direction: row !important;\n  }\n\n  .flex-sm-column {\n    flex-direction: column !important;\n  }\n\n  .flex-sm-row-reverse {\n    flex-direction: row-reverse !important;\n  }\n\n  .flex-sm-column-reverse {\n    flex-direction: column-reverse !important;\n  }\n\n  .flex-sm-grow-0 {\n    flex-grow: 0 !important;\n  }\n\n  .flex-sm-grow-1 {\n    flex-grow: 1 !important;\n  }\n\n  .flex-sm-shrink-0 {\n    flex-shrink: 0 !important;\n  }\n\n  .flex-sm-shrink-1 {\n    flex-shrink: 1 !important;\n  }\n\n  .flex-sm-wrap {\n    flex-wrap: wrap !important;\n  }\n\n  .flex-sm-nowrap {\n    flex-wrap: nowrap !important;\n  }\n\n  .flex-sm-wrap-reverse {\n    flex-wrap: wrap-reverse !important;\n  }\n\n  .gap-sm-0 {\n    gap: 0 !important;\n  }\n\n  .gap-sm-1 {\n    gap: 0.25rem !important;\n  }\n\n  .gap-sm-2 {\n    gap: 0.5rem !important;\n  }\n\n  .gap-sm-3 {\n    gap: 1rem !important;\n  }\n\n  .gap-sm-4 {\n    gap: 1.5rem !important;\n  }\n\n  .gap-sm-5 {\n    gap: 3rem !important;\n  }\n\n  .justify-content-sm-start {\n    justify-content: flex-start !important;\n  }\n\n  .justify-content-sm-end {\n    justify-content: flex-end !important;\n  }\n\n  .justify-content-sm-center {\n    justify-content: center !important;\n  }\n\n  .justify-content-sm-between {\n    justify-content: space-between !important;\n  }\n\n  .justify-content-sm-around {\n    justify-content: space-around !important;\n  }\n\n  .justify-content-sm-evenly {\n    justify-content: space-evenly !important;\n  }\n\n  .align-items-sm-start {\n    align-items: flex-start !important;\n  }\n\n  .align-items-sm-end {\n    align-items: flex-end !important;\n  }\n\n  .align-items-sm-center {\n    align-items: center !important;\n  }\n\n  .align-items-sm-baseline {\n    align-items: baseline !important;\n  }\n\n  .align-items-sm-stretch {\n    align-items: stretch !important;\n  }\n\n  .align-content-sm-start {\n    align-content: flex-start !important;\n  }\n\n  .align-content-sm-end {\n    align-content: flex-end !important;\n  }\n\n  .align-content-sm-center {\n    align-content: center !important;\n  }\n\n  .align-content-sm-between {\n    align-content: space-between !important;\n  }\n\n  .align-content-sm-around {\n    align-content: space-around !important;\n  }\n\n  .align-content-sm-stretch {\n    align-content: stretch !important;\n  }\n\n  .align-self-sm-auto {\n    align-self: auto !important;\n  }\n\n  .align-self-sm-start {\n    align-self: flex-start !important;\n  }\n\n  .align-self-sm-end {\n    align-self: flex-end !important;\n  }\n\n  .align-self-sm-center {\n    align-self: center !important;\n  }\n\n  .align-self-sm-baseline {\n    align-self: baseline !important;\n  }\n\n  .align-self-sm-stretch {\n    align-self: stretch !important;\n  }\n\n  .order-sm-first {\n    order: -1 !important;\n  }\n\n  .order-sm-0 {\n    order: 0 !important;\n  }\n\n  .order-sm-1 {\n    order: 1 !important;\n  }\n\n  .order-sm-2 {\n    order: 2 !important;\n  }\n\n  .order-sm-3 {\n    order: 3 !important;\n  }\n\n  .order-sm-4 {\n    order: 4 !important;\n  }\n\n  .order-sm-5 {\n    order: 5 !important;\n  }\n\n  .order-sm-last {\n    order: 6 !important;\n  }\n\n  .m-sm-0 {\n    margin: 0 !important;\n  }\n\n  .m-sm-1 {\n    margin: 0.25rem !important;\n  }\n\n  .m-sm-2 {\n    margin: 0.5rem !important;\n  }\n\n  .m-sm-3 {\n    margin: 1rem !important;\n  }\n\n  .m-sm-4 {\n    margin: 1.5rem !important;\n  }\n\n  .m-sm-5 {\n    margin: 3rem !important;\n  }\n\n  .m-sm-auto {\n    margin: auto !important;\n  }\n\n  .mx-sm-0 {\n    margin-right: 0 !important;\n    margin-left: 0 !important;\n  }\n\n  .mx-sm-1 {\n    margin-right: 0.25rem !important;\n    margin-left: 0.25rem !important;\n  }\n\n  .mx-sm-2 {\n    margin-right: 0.5rem !important;\n    margin-left: 0.5rem !important;\n  }\n\n  .mx-sm-3 {\n    margin-right: 1rem !important;\n    margin-left: 1rem !important;\n  }\n\n  .mx-sm-4 {\n    margin-right: 1.5rem !important;\n    margin-left: 1.5rem !important;\n  }\n\n  .mx-sm-5 {\n    margin-right: 3rem !important;\n    margin-left: 3rem !important;\n  }\n\n  .mx-sm-auto {\n    margin-right: auto !important;\n    margin-left: auto !important;\n  }\n\n  .my-sm-0 {\n    margin-top: 0 !important;\n    margin-bottom: 0 !important;\n  }\n\n  .my-sm-1 {\n    margin-top: 0.25rem !important;\n    margin-bottom: 0.25rem !important;\n  }\n\n  .my-sm-2 {\n    margin-top: 0.5rem !important;\n    margin-bottom: 0.5rem !important;\n  }\n\n  .my-sm-3 {\n    margin-top: 1rem !important;\n    margin-bottom: 1rem !important;\n  }\n\n  .my-sm-4 {\n    margin-top: 1.5rem !important;\n    margin-bottom: 1.5rem !important;\n  }\n\n  .my-sm-5 {\n    margin-top: 3rem !important;\n    margin-bottom: 3rem !important;\n  }\n\n  .my-sm-auto {\n    margin-top: auto !important;\n    margin-bottom: auto !important;\n  }\n\n  .mt-sm-0 {\n    margin-top: 0 !important;\n  }\n\n  .mt-sm-1 {\n    margin-top: 0.25rem !important;\n  }\n\n  .mt-sm-2 {\n    margin-top: 0.5rem !important;\n  }\n\n  .mt-sm-3 {\n    margin-top: 1rem !important;\n  }\n\n  .mt-sm-4 {\n    margin-top: 1.5rem !important;\n  }\n\n  .mt-sm-5 {\n    margin-top: 3rem !important;\n  }\n\n  .mt-sm-auto {\n    margin-top: auto !important;\n  }\n\n  .me-sm-0 {\n    margin-right: 0 !important;\n  }\n\n  .me-sm-1 {\n    margin-right: 0.25rem !important;\n  }\n\n  .me-sm-2 {\n    margin-right: 0.5rem !important;\n  }\n\n  .me-sm-3 {\n    margin-right: 1rem !important;\n  }\n\n  .me-sm-4 {\n    margin-right: 1.5rem !important;\n  }\n\n  .me-sm-5 {\n    margin-right: 3rem !important;\n  }\n\n  .me-sm-auto {\n    margin-right: auto !important;\n  }\n\n  .mb-sm-0 {\n    margin-bottom: 0 !important;\n  }\n\n  .mb-sm-1 {\n    margin-bottom: 0.25rem !important;\n  }\n\n  .mb-sm-2 {\n    margin-bottom: 0.5rem !important;\n  }\n\n  .mb-sm-3 {\n    margin-bottom: 1rem !important;\n  }\n\n  .mb-sm-4 {\n    margin-bottom: 1.5rem !important;\n  }\n\n  .mb-sm-5 {\n    margin-bottom: 3rem !important;\n  }\n\n  .mb-sm-auto {\n    margin-bottom: auto !important;\n  }\n\n  .ms-sm-0 {\n    margin-left: 0 !important;\n  }\n\n  .ms-sm-1 {\n    margin-left: 0.25rem !important;\n  }\n\n  .ms-sm-2 {\n    margin-left: 0.5rem !important;\n  }\n\n  .ms-sm-3 {\n    margin-left: 1rem !important;\n  }\n\n  .ms-sm-4 {\n    margin-left: 1.5rem !important;\n  }\n\n  .ms-sm-5 {\n    margin-left: 3rem !important;\n  }\n\n  .ms-sm-auto {\n    margin-left: auto !important;\n  }\n\n  .p-sm-0 {\n    padding: 0 !important;\n  }\n\n  .p-sm-1 {\n    padding: 0.25rem !important;\n  }\n\n  .p-sm-2 {\n    padding: 0.5rem !important;\n  }\n\n  .p-sm-3 {\n    padding: 1rem !important;\n  }\n\n  .p-sm-4 {\n    padding: 1.5rem !important;\n  }\n\n  .p-sm-5 {\n    padding: 3rem !important;\n  }\n\n  .px-sm-0 {\n    padding-right: 0 !important;\n    padding-left: 0 !important;\n  }\n\n  .px-sm-1 {\n    padding-right: 0.25rem !important;\n    padding-left: 0.25rem !important;\n  }\n\n  .px-sm-2 {\n    padding-right: 0.5rem !important;\n    padding-left: 0.5rem !important;\n  }\n\n  .px-sm-3 {\n    padding-right: 1rem !important;\n    padding-left: 1rem !important;\n  }\n\n  .px-sm-4 {\n    padding-right: 1.5rem !important;\n    padding-left: 1.5rem !important;\n  }\n\n  .px-sm-5 {\n    padding-right: 3rem !important;\n    padding-left: 3rem !important;\n  }\n\n  .py-sm-0 {\n    padding-top: 0 !important;\n    padding-bottom: 0 !important;\n  }\n\n  .py-sm-1 {\n    padding-top: 0.25rem !important;\n    padding-bottom: 0.25rem !important;\n  }\n\n  .py-sm-2 {\n    padding-top: 0.5rem !important;\n    padding-bottom: 0.5rem !important;\n  }\n\n  .py-sm-3 {\n    padding-top: 1rem !important;\n    padding-bottom: 1rem !important;\n  }\n\n  .py-sm-4 {\n    padding-top: 1.5rem !important;\n    padding-bottom: 1.5rem !important;\n  }\n\n  .py-sm-5 {\n    padding-top: 3rem !important;\n    padding-bottom: 3rem !important;\n  }\n\n  .pt-sm-0 {\n    padding-top: 0 !important;\n  }\n\n  .pt-sm-1 {\n    padding-top: 0.25rem !important;\n  }\n\n  .pt-sm-2 {\n    padding-top: 0.5rem !important;\n  }\n\n  .pt-sm-3 {\n    padding-top: 1rem !important;\n  }\n\n  .pt-sm-4 {\n    padding-top: 1.5rem !important;\n  }\n\n  .pt-sm-5 {\n    padding-top: 3rem !important;\n  }\n\n  .pe-sm-0 {\n    padding-right: 0 !important;\n  }\n\n  .pe-sm-1 {\n    padding-right: 0.25rem !important;\n  }\n\n  .pe-sm-2 {\n    padding-right: 0.5rem !important;\n  }\n\n  .pe-sm-3 {\n    padding-right: 1rem !important;\n  }\n\n  .pe-sm-4 {\n    padding-right: 1.5rem !important;\n  }\n\n  .pe-sm-5 {\n    padding-right: 3rem !important;\n  }\n\n  .pb-sm-0 {\n    padding-bottom: 0 !important;\n  }\n\n  .pb-sm-1 {\n    padding-bottom: 0.25rem !important;\n  }\n\n  .pb-sm-2 {\n    padding-bottom: 0.5rem !important;\n  }\n\n  .pb-sm-3 {\n    padding-bottom: 1rem !important;\n  }\n\n  .pb-sm-4 {\n    padding-bottom: 1.5rem !important;\n  }\n\n  .pb-sm-5 {\n    padding-bottom: 3rem !important;\n  }\n\n  .ps-sm-0 {\n    padding-left: 0 !important;\n  }\n\n  .ps-sm-1 {\n    padding-left: 0.25rem !important;\n  }\n\n  .ps-sm-2 {\n    padding-left: 0.5rem !important;\n  }\n\n  .ps-sm-3 {\n    padding-left: 1rem !important;\n  }\n\n  .ps-sm-4 {\n    padding-left: 1.5rem !important;\n  }\n\n  .ps-sm-5 {\n    padding-left: 3rem !important;\n  }\n\n  .text-sm-start {\n    text-align: left !important;\n  }\n\n  .text-sm-end {\n    text-align: right !important;\n  }\n\n  .text-sm-center {\n    text-align: center !important;\n  }\n}\n@media (min-width: 768px) {\n  .float-md-start {\n    float: left !important;\n  }\n\n  .float-md-end {\n    float: right !important;\n  }\n\n  .float-md-none {\n    float: none !important;\n  }\n\n  .d-md-inline {\n    display: inline !important;\n  }\n\n  .d-md-inline-block {\n    display: inline-block !important;\n  }\n\n  .d-md-block {\n    display: block !important;\n  }\n\n  .d-md-grid {\n    display: grid !important;\n  }\n\n  .d-md-table {\n    display: table !important;\n  }\n\n  .d-md-table-row {\n    display: table-row !important;\n  }\n\n  .d-md-table-cell {\n    display: table-cell !important;\n  }\n\n  .d-md-flex {\n    display: flex !important;\n  }\n\n  .d-md-inline-flex {\n    display: inline-flex !important;\n  }\n\n  .d-md-none {\n    display: none !important;\n  }\n\n  .flex-md-fill {\n    flex: 1 1 auto !important;\n  }\n\n  .flex-md-row {\n    flex-direction: row !important;\n  }\n\n  .flex-md-column {\n    flex-direction: column !important;\n  }\n\n  .flex-md-row-reverse {\n    flex-direction: row-reverse !important;\n  }\n\n  .flex-md-column-reverse {\n    flex-direction: column-reverse !important;\n  }\n\n  .flex-md-grow-0 {\n    flex-grow: 0 !important;\n  }\n\n  .flex-md-grow-1 {\n    flex-grow: 1 !important;\n  }\n\n  .flex-md-shrink-0 {\n    flex-shrink: 0 !important;\n  }\n\n  .flex-md-shrink-1 {\n    flex-shrink: 1 !important;\n  }\n\n  .flex-md-wrap {\n    flex-wrap: wrap !important;\n  }\n\n  .flex-md-nowrap {\n    flex-wrap: nowrap !important;\n  }\n\n  .flex-md-wrap-reverse {\n    flex-wrap: wrap-reverse !important;\n  }\n\n  .gap-md-0 {\n    gap: 0 !important;\n  }\n\n  .gap-md-1 {\n    gap: 0.25rem !important;\n  }\n\n  .gap-md-2 {\n    gap: 0.5rem !important;\n  }\n\n  .gap-md-3 {\n    gap: 1rem !important;\n  }\n\n  .gap-md-4 {\n    gap: 1.5rem !important;\n  }\n\n  .gap-md-5 {\n    gap: 3rem !important;\n  }\n\n  .justify-content-md-start {\n    justify-content: flex-start !important;\n  }\n\n  .justify-content-md-end {\n    justify-content: flex-end !important;\n  }\n\n  .justify-content-md-center {\n    justify-content: center !important;\n  }\n\n  .justify-content-md-between {\n    justify-content: space-between !important;\n  }\n\n  .justify-content-md-around {\n    justify-content: space-around !important;\n  }\n\n  .justify-content-md-evenly {\n    justify-content: space-evenly !important;\n  }\n\n  .align-items-md-start {\n    align-items: flex-start !important;\n  }\n\n  .align-items-md-end {\n    align-items: flex-end !important;\n  }\n\n  .align-items-md-center {\n    align-items: center !important;\n  }\n\n  .align-items-md-baseline {\n    align-items: baseline !important;\n  }\n\n  .align-items-md-stretch {\n    align-items: stretch !important;\n  }\n\n  .align-content-md-start {\n    align-content: flex-start !important;\n  }\n\n  .align-content-md-end {\n    align-content: flex-end !important;\n  }\n\n  .align-content-md-center {\n    align-content: center !important;\n  }\n\n  .align-content-md-between {\n    align-content: space-between !important;\n  }\n\n  .align-content-md-around {\n    align-content: space-around !important;\n  }\n\n  .align-content-md-stretch {\n    align-content: stretch !important;\n  }\n\n  .align-self-md-auto {\n    align-self: auto !important;\n  }\n\n  .align-self-md-start {\n    align-self: flex-start !important;\n  }\n\n  .align-self-md-end {\n    align-self: flex-end !important;\n  }\n\n  .align-self-md-center {\n    align-self: center !important;\n  }\n\n  .align-self-md-baseline {\n    align-self: baseline !important;\n  }\n\n  .align-self-md-stretch {\n    align-self: stretch !important;\n  }\n\n  .order-md-first {\n    order: -1 !important;\n  }\n\n  .order-md-0 {\n    order: 0 !important;\n  }\n\n  .order-md-1 {\n    order: 1 !important;\n  }\n\n  .order-md-2 {\n    order: 2 !important;\n  }\n\n  .order-md-3 {\n    order: 3 !important;\n  }\n\n  .order-md-4 {\n    order: 4 !important;\n  }\n\n  .order-md-5 {\n    order: 5 !important;\n  }\n\n  .order-md-last {\n    order: 6 !important;\n  }\n\n  .m-md-0 {\n    margin: 0 !important;\n  }\n\n  .m-md-1 {\n    margin: 0.25rem !important;\n  }\n\n  .m-md-2 {\n    margin: 0.5rem !important;\n  }\n\n  .m-md-3 {\n    margin: 1rem !important;\n  }\n\n  .m-md-4 {\n    margin: 1.5rem !important;\n  }\n\n  .m-md-5 {\n    margin: 3rem !important;\n  }\n\n  .m-md-auto {\n    margin: auto !important;\n  }\n\n  .mx-md-0 {\n    margin-right: 0 !important;\n    margin-left: 0 !important;\n  }\n\n  .mx-md-1 {\n    margin-right: 0.25rem !important;\n    margin-left: 0.25rem !important;\n  }\n\n  .mx-md-2 {\n    margin-right: 0.5rem !important;\n    margin-left: 0.5rem !important;\n  }\n\n  .mx-md-3 {\n    margin-right: 1rem !important;\n    margin-left: 1rem !important;\n  }\n\n  .mx-md-4 {\n    margin-right: 1.5rem !important;\n    margin-left: 1.5rem !important;\n  }\n\n  .mx-md-5 {\n    margin-right: 3rem !important;\n    margin-left: 3rem !important;\n  }\n\n  .mx-md-auto {\n    margin-right: auto !important;\n    margin-left: auto !important;\n  }\n\n  .my-md-0 {\n    margin-top: 0 !important;\n    margin-bottom: 0 !important;\n  }\n\n  .my-md-1 {\n    margin-top: 0.25rem !important;\n    margin-bottom: 0.25rem !important;\n  }\n\n  .my-md-2 {\n    margin-top: 0.5rem !important;\n    margin-bottom: 0.5rem !important;\n  }\n\n  .my-md-3 {\n    margin-top: 1rem !important;\n    margin-bottom: 1rem !important;\n  }\n\n  .my-md-4 {\n    margin-top: 1.5rem !important;\n    margin-bottom: 1.5rem !important;\n  }\n\n  .my-md-5 {\n    margin-top: 3rem !important;\n    margin-bottom: 3rem !important;\n  }\n\n  .my-md-auto {\n    margin-top: auto !important;\n    margin-bottom: auto !important;\n  }\n\n  .mt-md-0 {\n    margin-top: 0 !important;\n  }\n\n  .mt-md-1 {\n    margin-top: 0.25rem !important;\n  }\n\n  .mt-md-2 {\n    margin-top: 0.5rem !important;\n  }\n\n  .mt-md-3 {\n    margin-top: 1rem !important;\n  }\n\n  .mt-md-4 {\n    margin-top: 1.5rem !important;\n  }\n\n  .mt-md-5 {\n    margin-top: 3rem !important;\n  }\n\n  .mt-md-auto {\n    margin-top: auto !important;\n  }\n\n  .me-md-0 {\n    margin-right: 0 !important;\n  }\n\n  .me-md-1 {\n    margin-right: 0.25rem !important;\n  }\n\n  .me-md-2 {\n    margin-right: 0.5rem !important;\n  }\n\n  .me-md-3 {\n    margin-right: 1rem !important;\n  }\n\n  .me-md-4 {\n    margin-right: 1.5rem !important;\n  }\n\n  .me-md-5 {\n    margin-right: 3rem !important;\n  }\n\n  .me-md-auto {\n    margin-right: auto !important;\n  }\n\n  .mb-md-0 {\n    margin-bottom: 0 !important;\n  }\n\n  .mb-md-1 {\n    margin-bottom: 0.25rem !important;\n  }\n\n  .mb-md-2 {\n    margin-bottom: 0.5rem !important;\n  }\n\n  .mb-md-3 {\n    margin-bottom: 1rem !important;\n  }\n\n  .mb-md-4 {\n    margin-bottom: 1.5rem !important;\n  }\n\n  .mb-md-5 {\n    margin-bottom: 3rem !important;\n  }\n\n  .mb-md-auto {\n    margin-bottom: auto !important;\n  }\n\n  .ms-md-0 {\n    margin-left: 0 !important;\n  }\n\n  .ms-md-1 {\n    margin-left: 0.25rem !important;\n  }\n\n  .ms-md-2 {\n    margin-left: 0.5rem !important;\n  }\n\n  .ms-md-3 {\n    margin-left: 1rem !important;\n  }\n\n  .ms-md-4 {\n    margin-left: 1.5rem !important;\n  }\n\n  .ms-md-5 {\n    margin-left: 3rem !important;\n  }\n\n  .ms-md-auto {\n    margin-left: auto !important;\n  }\n\n  .p-md-0 {\n    padding: 0 !important;\n  }\n\n  .p-md-1 {\n    padding: 0.25rem !important;\n  }\n\n  .p-md-2 {\n    padding: 0.5rem !important;\n  }\n\n  .p-md-3 {\n    padding: 1rem !important;\n  }\n\n  .p-md-4 {\n    padding: 1.5rem !important;\n  }\n\n  .p-md-5 {\n    padding: 3rem !important;\n  }\n\n  .px-md-0 {\n    padding-right: 0 !important;\n    padding-left: 0 !important;\n  }\n\n  .px-md-1 {\n    padding-right: 0.25rem !important;\n    padding-left: 0.25rem !important;\n  }\n\n  .px-md-2 {\n    padding-right: 0.5rem !important;\n    padding-left: 0.5rem !important;\n  }\n\n  .px-md-3 {\n    padding-right: 1rem !important;\n    padding-left: 1rem !important;\n  }\n\n  .px-md-4 {\n    padding-right: 1.5rem !important;\n    padding-left: 1.5rem !important;\n  }\n\n  .px-md-5 {\n    padding-right: 3rem !important;\n    padding-left: 3rem !important;\n  }\n\n  .py-md-0 {\n    padding-top: 0 !important;\n    padding-bottom: 0 !important;\n  }\n\n  .py-md-1 {\n    padding-top: 0.25rem !important;\n    padding-bottom: 0.25rem !important;\n  }\n\n  .py-md-2 {\n    padding-top: 0.5rem !important;\n    padding-bottom: 0.5rem !important;\n  }\n\n  .py-md-3 {\n    padding-top: 1rem !important;\n    padding-bottom: 1rem !important;\n  }\n\n  .py-md-4 {\n    padding-top: 1.5rem !important;\n    padding-bottom: 1.5rem !important;\n  }\n\n  .py-md-5 {\n    padding-top: 3rem !important;\n    padding-bottom: 3rem !important;\n  }\n\n  .pt-md-0 {\n    padding-top: 0 !important;\n  }\n\n  .pt-md-1 {\n    padding-top: 0.25rem !important;\n  }\n\n  .pt-md-2 {\n    padding-top: 0.5rem !important;\n  }\n\n  .pt-md-3 {\n    padding-top: 1rem !important;\n  }\n\n  .pt-md-4 {\n    padding-top: 1.5rem !important;\n  }\n\n  .pt-md-5 {\n    padding-top: 3rem !important;\n  }\n\n  .pe-md-0 {\n    padding-right: 0 !important;\n  }\n\n  .pe-md-1 {\n    padding-right: 0.25rem !important;\n  }\n\n  .pe-md-2 {\n    padding-right: 0.5rem !important;\n  }\n\n  .pe-md-3 {\n    padding-right: 1rem !important;\n  }\n\n  .pe-md-4 {\n    padding-right: 1.5rem !important;\n  }\n\n  .pe-md-5 {\n    padding-right: 3rem !important;\n  }\n\n  .pb-md-0 {\n    padding-bottom: 0 !important;\n  }\n\n  .pb-md-1 {\n    padding-bottom: 0.25rem !important;\n  }\n\n  .pb-md-2 {\n    padding-bottom: 0.5rem !important;\n  }\n\n  .pb-md-3 {\n    padding-bottom: 1rem !important;\n  }\n\n  .pb-md-4 {\n    padding-bottom: 1.5rem !important;\n  }\n\n  .pb-md-5 {\n    padding-bottom: 3rem !important;\n  }\n\n  .ps-md-0 {\n    padding-left: 0 !important;\n  }\n\n  .ps-md-1 {\n    padding-left: 0.25rem !important;\n  }\n\n  .ps-md-2 {\n    padding-left: 0.5rem !important;\n  }\n\n  .ps-md-3 {\n    padding-left: 1rem !important;\n  }\n\n  .ps-md-4 {\n    padding-left: 1.5rem !important;\n  }\n\n  .ps-md-5 {\n    padding-left: 3rem !important;\n  }\n\n  .text-md-start {\n    text-align: left !important;\n  }\n\n  .text-md-end {\n    text-align: right !important;\n  }\n\n  .text-md-center {\n    text-align: center !important;\n  }\n}\n@media (min-width: 992px) {\n  .float-lg-start {\n    float: left !important;\n  }\n\n  .float-lg-end {\n    float: right !important;\n  }\n\n  .float-lg-none {\n    float: none !important;\n  }\n\n  .d-lg-inline {\n    display: inline !important;\n  }\n\n  .d-lg-inline-block {\n    display: inline-block !important;\n  }\n\n  .d-lg-block {\n    display: block !important;\n  }\n\n  .d-lg-grid {\n    display: grid !important;\n  }\n\n  .d-lg-table {\n    display: table !important;\n  }\n\n  .d-lg-table-row {\n    display: table-row !important;\n  }\n\n  .d-lg-table-cell {\n    display: table-cell !important;\n  }\n\n  .d-lg-flex {\n    display: flex !important;\n  }\n\n  .d-lg-inline-flex {\n    display: inline-flex !important;\n  }\n\n  .d-lg-none {\n    display: none !important;\n  }\n\n  .flex-lg-fill {\n    flex: 1 1 auto !important;\n  }\n\n  .flex-lg-row {\n    flex-direction: row !important;\n  }\n\n  .flex-lg-column {\n    flex-direction: column !important;\n  }\n\n  .flex-lg-row-reverse {\n    flex-direction: row-reverse !important;\n  }\n\n  .flex-lg-column-reverse {\n    flex-direction: column-reverse !important;\n  }\n\n  .flex-lg-grow-0 {\n    flex-grow: 0 !important;\n  }\n\n  .flex-lg-grow-1 {\n    flex-grow: 1 !important;\n  }\n\n  .flex-lg-shrink-0 {\n    flex-shrink: 0 !important;\n  }\n\n  .flex-lg-shrink-1 {\n    flex-shrink: 1 !important;\n  }\n\n  .flex-lg-wrap {\n    flex-wrap: wrap !important;\n  }\n\n  .flex-lg-nowrap {\n    flex-wrap: nowrap !important;\n  }\n\n  .flex-lg-wrap-reverse {\n    flex-wrap: wrap-reverse !important;\n  }\n\n  .gap-lg-0 {\n    gap: 0 !important;\n  }\n\n  .gap-lg-1 {\n    gap: 0.25rem !important;\n  }\n\n  .gap-lg-2 {\n    gap: 0.5rem !important;\n  }\n\n  .gap-lg-3 {\n    gap: 1rem !important;\n  }\n\n  .gap-lg-4 {\n    gap: 1.5rem !important;\n  }\n\n  .gap-lg-5 {\n    gap: 3rem !important;\n  }\n\n  .justify-content-lg-start {\n    justify-content: flex-start !important;\n  }\n\n  .justify-content-lg-end {\n    justify-content: flex-end !important;\n  }\n\n  .justify-content-lg-center {\n    justify-content: center !important;\n  }\n\n  .justify-content-lg-between {\n    justify-content: space-between !important;\n  }\n\n  .justify-content-lg-around {\n    justify-content: space-around !important;\n  }\n\n  .justify-content-lg-evenly {\n    justify-content: space-evenly !important;\n  }\n\n  .align-items-lg-start {\n    align-items: flex-start !important;\n  }\n\n  .align-items-lg-end {\n    align-items: flex-end !important;\n  }\n\n  .align-items-lg-center {\n    align-items: center !important;\n  }\n\n  .align-items-lg-baseline {\n    align-items: baseline !important;\n  }\n\n  .align-items-lg-stretch {\n    align-items: stretch !important;\n  }\n\n  .align-content-lg-start {\n    align-content: flex-start !important;\n  }\n\n  .align-content-lg-end {\n    align-content: flex-end !important;\n  }\n\n  .align-content-lg-center {\n    align-content: center !important;\n  }\n\n  .align-content-lg-between {\n    align-content: space-between !important;\n  }\n\n  .align-content-lg-around {\n    align-content: space-around !important;\n  }\n\n  .align-content-lg-stretch {\n    align-content: stretch !important;\n  }\n\n  .align-self-lg-auto {\n    align-self: auto !important;\n  }\n\n  .align-self-lg-start {\n    align-self: flex-start !important;\n  }\n\n  .align-self-lg-end {\n    align-self: flex-end !important;\n  }\n\n  .align-self-lg-center {\n    align-self: center !important;\n  }\n\n  .align-self-lg-baseline {\n    align-self: baseline !important;\n  }\n\n  .align-self-lg-stretch {\n    align-self: stretch !important;\n  }\n\n  .order-lg-first {\n    order: -1 !important;\n  }\n\n  .order-lg-0 {\n    order: 0 !important;\n  }\n\n  .order-lg-1 {\n    order: 1 !important;\n  }\n\n  .order-lg-2 {\n    order: 2 !important;\n  }\n\n  .order-lg-3 {\n    order: 3 !important;\n  }\n\n  .order-lg-4 {\n    order: 4 !important;\n  }\n\n  .order-lg-5 {\n    order: 5 !important;\n  }\n\n  .order-lg-last {\n    order: 6 !important;\n  }\n\n  .m-lg-0 {\n    margin: 0 !important;\n  }\n\n  .m-lg-1 {\n    margin: 0.25rem !important;\n  }\n\n  .m-lg-2 {\n    margin: 0.5rem !important;\n  }\n\n  .m-lg-3 {\n    margin: 1rem !important;\n  }\n\n  .m-lg-4 {\n    margin: 1.5rem !important;\n  }\n\n  .m-lg-5 {\n    margin: 3rem !important;\n  }\n\n  .m-lg-auto {\n    margin: auto !important;\n  }\n\n  .mx-lg-0 {\n    margin-right: 0 !important;\n    margin-left: 0 !important;\n  }\n\n  .mx-lg-1 {\n    margin-right: 0.25rem !important;\n    margin-left: 0.25rem !important;\n  }\n\n  .mx-lg-2 {\n    margin-right: 0.5rem !important;\n    margin-left: 0.5rem !important;\n  }\n\n  .mx-lg-3 {\n    margin-right: 1rem !important;\n    margin-left: 1rem !important;\n  }\n\n  .mx-lg-4 {\n    margin-right: 1.5rem !important;\n    margin-left: 1.5rem !important;\n  }\n\n  .mx-lg-5 {\n    margin-right: 3rem !important;\n    margin-left: 3rem !important;\n  }\n\n  .mx-lg-auto {\n    margin-right: auto !important;\n    margin-left: auto !important;\n  }\n\n  .my-lg-0 {\n    margin-top: 0 !important;\n    margin-bottom: 0 !important;\n  }\n\n  .my-lg-1 {\n    margin-top: 0.25rem !important;\n    margin-bottom: 0.25rem !important;\n  }\n\n  .my-lg-2 {\n    margin-top: 0.5rem !important;\n    margin-bottom: 0.5rem !important;\n  }\n\n  .my-lg-3 {\n    margin-top: 1rem !important;\n    margin-bottom: 1rem !important;\n  }\n\n  .my-lg-4 {\n    margin-top: 1.5rem !important;\n    margin-bottom: 1.5rem !important;\n  }\n\n  .my-lg-5 {\n    margin-top: 3rem !important;\n    margin-bottom: 3rem !important;\n  }\n\n  .my-lg-auto {\n    margin-top: auto !important;\n    margin-bottom: auto !important;\n  }\n\n  .mt-lg-0 {\n    margin-top: 0 !important;\n  }\n\n  .mt-lg-1 {\n    margin-top: 0.25rem !important;\n  }\n\n  .mt-lg-2 {\n    margin-top: 0.5rem !important;\n  }\n\n  .mt-lg-3 {\n    margin-top: 1rem !important;\n  }\n\n  .mt-lg-4 {\n    margin-top: 1.5rem !important;\n  }\n\n  .mt-lg-5 {\n    margin-top: 3rem !important;\n  }\n\n  .mt-lg-auto {\n    margin-top: auto !important;\n  }\n\n  .me-lg-0 {\n    margin-right: 0 !important;\n  }\n\n  .me-lg-1 {\n    margin-right: 0.25rem !important;\n  }\n\n  .me-lg-2 {\n    margin-right: 0.5rem !important;\n  }\n\n  .me-lg-3 {\n    margin-right: 1rem !important;\n  }\n\n  .me-lg-4 {\n    margin-right: 1.5rem !important;\n  }\n\n  .me-lg-5 {\n    margin-right: 3rem !important;\n  }\n\n  .me-lg-auto {\n    margin-right: auto !important;\n  }\n\n  .mb-lg-0 {\n    margin-bottom: 0 !important;\n  }\n\n  .mb-lg-1 {\n    margin-bottom: 0.25rem !important;\n  }\n\n  .mb-lg-2 {\n    margin-bottom: 0.5rem !important;\n  }\n\n  .mb-lg-3 {\n    margin-bottom: 1rem !important;\n  }\n\n  .mb-lg-4 {\n    margin-bottom: 1.5rem !important;\n  }\n\n  .mb-lg-5 {\n    margin-bottom: 3rem !important;\n  }\n\n  .mb-lg-auto {\n    margin-bottom: auto !important;\n  }\n\n  .ms-lg-0 {\n    margin-left: 0 !important;\n  }\n\n  .ms-lg-1 {\n    margin-left: 0.25rem !important;\n  }\n\n  .ms-lg-2 {\n    margin-left: 0.5rem !important;\n  }\n\n  .ms-lg-3 {\n    margin-left: 1rem !important;\n  }\n\n  .ms-lg-4 {\n    margin-left: 1.5rem !important;\n  }\n\n  .ms-lg-5 {\n    margin-left: 3rem !important;\n  }\n\n  .ms-lg-auto {\n    margin-left: auto !important;\n  }\n\n  .p-lg-0 {\n    padding: 0 !important;\n  }\n\n  .p-lg-1 {\n    padding: 0.25rem !important;\n  }\n\n  .p-lg-2 {\n    padding: 0.5rem !important;\n  }\n\n  .p-lg-3 {\n    padding: 1rem !important;\n  }\n\n  .p-lg-4 {\n    padding: 1.5rem !important;\n  }\n\n  .p-lg-5 {\n    padding: 3rem !important;\n  }\n\n  .px-lg-0 {\n    padding-right: 0 !important;\n    padding-left: 0 !important;\n  }\n\n  .px-lg-1 {\n    padding-right: 0.25rem !important;\n    padding-left: 0.25rem !important;\n  }\n\n  .px-lg-2 {\n    padding-right: 0.5rem !important;\n    padding-left: 0.5rem !important;\n  }\n\n  .px-lg-3 {\n    padding-right: 1rem !important;\n    padding-left: 1rem !important;\n  }\n\n  .px-lg-4 {\n    padding-right: 1.5rem !important;\n    padding-left: 1.5rem !important;\n  }\n\n  .px-lg-5 {\n    padding-right: 3rem !important;\n    padding-left: 3rem !important;\n  }\n\n  .py-lg-0 {\n    padding-top: 0 !important;\n    padding-bottom: 0 !important;\n  }\n\n  .py-lg-1 {\n    padding-top: 0.25rem !important;\n    padding-bottom: 0.25rem !important;\n  }\n\n  .py-lg-2 {\n    padding-top: 0.5rem !important;\n    padding-bottom: 0.5rem !important;\n  }\n\n  .py-lg-3 {\n    padding-top: 1rem !important;\n    padding-bottom: 1rem !important;\n  }\n\n  .py-lg-4 {\n    padding-top: 1.5rem !important;\n    padding-bottom: 1.5rem !important;\n  }\n\n  .py-lg-5 {\n    padding-top: 3rem !important;\n    padding-bottom: 3rem !important;\n  }\n\n  .pt-lg-0 {\n    padding-top: 0 !important;\n  }\n\n  .pt-lg-1 {\n    padding-top: 0.25rem !important;\n  }\n\n  .pt-lg-2 {\n    padding-top: 0.5rem !important;\n  }\n\n  .pt-lg-3 {\n    padding-top: 1rem !important;\n  }\n\n  .pt-lg-4 {\n    padding-top: 1.5rem !important;\n  }\n\n  .pt-lg-5 {\n    padding-top: 3rem !important;\n  }\n\n  .pe-lg-0 {\n    padding-right: 0 !important;\n  }\n\n  .pe-lg-1 {\n    padding-right: 0.25rem !important;\n  }\n\n  .pe-lg-2 {\n    padding-right: 0.5rem !important;\n  }\n\n  .pe-lg-3 {\n    padding-right: 1rem !important;\n  }\n\n  .pe-lg-4 {\n    padding-right: 1.5rem !important;\n  }\n\n  .pe-lg-5 {\n    padding-right: 3rem !important;\n  }\n\n  .pb-lg-0 {\n    padding-bottom: 0 !important;\n  }\n\n  .pb-lg-1 {\n    padding-bottom: 0.25rem !important;\n  }\n\n  .pb-lg-2 {\n    padding-bottom: 0.5rem !important;\n  }\n\n  .pb-lg-3 {\n    padding-bottom: 1rem !important;\n  }\n\n  .pb-lg-4 {\n    padding-bottom: 1.5rem !important;\n  }\n\n  .pb-lg-5 {\n    padding-bottom: 3rem !important;\n  }\n\n  .ps-lg-0 {\n    padding-left: 0 !important;\n  }\n\n  .ps-lg-1 {\n    padding-left: 0.25rem !important;\n  }\n\n  .ps-lg-2 {\n    padding-left: 0.5rem !important;\n  }\n\n  .ps-lg-3 {\n    padding-left: 1rem !important;\n  }\n\n  .ps-lg-4 {\n    padding-left: 1.5rem !important;\n  }\n\n  .ps-lg-5 {\n    padding-left: 3rem !important;\n  }\n\n  .text-lg-start {\n    text-align: left !important;\n  }\n\n  .text-lg-end {\n    text-align: right !important;\n  }\n\n  .text-lg-center {\n    text-align: center !important;\n  }\n}\n@media (min-width: 1200px) {\n  .float-xl-start {\n    float: left !important;\n  }\n\n  .float-xl-end {\n    float: right !important;\n  }\n\n  .float-xl-none {\n    float: none !important;\n  }\n\n  .d-xl-inline {\n    display: inline !important;\n  }\n\n  .d-xl-inline-block {\n    display: inline-block !important;\n  }\n\n  .d-xl-block {\n    display: block !important;\n  }\n\n  .d-xl-grid {\n    display: grid !important;\n  }\n\n  .d-xl-table {\n    display: table !important;\n  }\n\n  .d-xl-table-row {\n    display: table-row !important;\n  }\n\n  .d-xl-table-cell {\n    display: table-cell !important;\n  }\n\n  .d-xl-flex {\n    display: flex !important;\n  }\n\n  .d-xl-inline-flex {\n    display: inline-flex !important;\n  }\n\n  .d-xl-none {\n    display: none !important;\n  }\n\n  .flex-xl-fill {\n    flex: 1 1 auto !important;\n  }\n\n  .flex-xl-row {\n    flex-direction: row !important;\n  }\n\n  .flex-xl-column {\n    flex-direction: column !important;\n  }\n\n  .flex-xl-row-reverse {\n    flex-direction: row-reverse !important;\n  }\n\n  .flex-xl-column-reverse {\n    flex-direction: column-reverse !important;\n  }\n\n  .flex-xl-grow-0 {\n    flex-grow: 0 !important;\n  }\n\n  .flex-xl-grow-1 {\n    flex-grow: 1 !important;\n  }\n\n  .flex-xl-shrink-0 {\n    flex-shrink: 0 !important;\n  }\n\n  .flex-xl-shrink-1 {\n    flex-shrink: 1 !important;\n  }\n\n  .flex-xl-wrap {\n    flex-wrap: wrap !important;\n  }\n\n  .flex-xl-nowrap {\n    flex-wrap: nowrap !important;\n  }\n\n  .flex-xl-wrap-reverse {\n    flex-wrap: wrap-reverse !important;\n  }\n\n  .gap-xl-0 {\n    gap: 0 !important;\n  }\n\n  .gap-xl-1 {\n    gap: 0.25rem !important;\n  }\n\n  .gap-xl-2 {\n    gap: 0.5rem !important;\n  }\n\n  .gap-xl-3 {\n    gap: 1rem !important;\n  }\n\n  .gap-xl-4 {\n    gap: 1.5rem !important;\n  }\n\n  .gap-xl-5 {\n    gap: 3rem !important;\n  }\n\n  .justify-content-xl-start {\n    justify-content: flex-start !important;\n  }\n\n  .justify-content-xl-end {\n    justify-content: flex-end !important;\n  }\n\n  .justify-content-xl-center {\n    justify-content: center !important;\n  }\n\n  .justify-content-xl-between {\n    justify-content: space-between !important;\n  }\n\n  .justify-content-xl-around {\n    justify-content: space-around !important;\n  }\n\n  .justify-content-xl-evenly {\n    justify-content: space-evenly !important;\n  }\n\n  .align-items-xl-start {\n    align-items: flex-start !important;\n  }\n\n  .align-items-xl-end {\n    align-items: flex-end !important;\n  }\n\n  .align-items-xl-center {\n    align-items: center !important;\n  }\n\n  .align-items-xl-baseline {\n    align-items: baseline !important;\n  }\n\n  .align-items-xl-stretch {\n    align-items: stretch !important;\n  }\n\n  .align-content-xl-start {\n    align-content: flex-start !important;\n  }\n\n  .align-content-xl-end {\n    align-content: flex-end !important;\n  }\n\n  .align-content-xl-center {\n    align-content: center !important;\n  }\n\n  .align-content-xl-between {\n    align-content: space-between !important;\n  }\n\n  .align-content-xl-around {\n    align-content: space-around !important;\n  }\n\n  .align-content-xl-stretch {\n    align-content: stretch !important;\n  }\n\n  .align-self-xl-auto {\n    align-self: auto !important;\n  }\n\n  .align-self-xl-start {\n    align-self: flex-start !important;\n  }\n\n  .align-self-xl-end {\n    align-self: flex-end !important;\n  }\n\n  .align-self-xl-center {\n    align-self: center !important;\n  }\n\n  .align-self-xl-baseline {\n    align-self: baseline !important;\n  }\n\n  .align-self-xl-stretch {\n    align-self: stretch !important;\n  }\n\n  .order-xl-first {\n    order: -1 !important;\n  }\n\n  .order-xl-0 {\n    order: 0 !important;\n  }\n\n  .order-xl-1 {\n    order: 1 !important;\n  }\n\n  .order-xl-2 {\n    order: 2 !important;\n  }\n\n  .order-xl-3 {\n    order: 3 !important;\n  }\n\n  .order-xl-4 {\n    order: 4 !important;\n  }\n\n  .order-xl-5 {\n    order: 5 !important;\n  }\n\n  .order-xl-last {\n    order: 6 !important;\n  }\n\n  .m-xl-0 {\n    margin: 0 !important;\n  }\n\n  .m-xl-1 {\n    margin: 0.25rem !important;\n  }\n\n  .m-xl-2 {\n    margin: 0.5rem !important;\n  }\n\n  .m-xl-3 {\n    margin: 1rem !important;\n  }\n\n  .m-xl-4 {\n    margin: 1.5rem !important;\n  }\n\n  .m-xl-5 {\n    margin: 3rem !important;\n  }\n\n  .m-xl-auto {\n    margin: auto !important;\n  }\n\n  .mx-xl-0 {\n    margin-right: 0 !important;\n    margin-left: 0 !important;\n  }\n\n  .mx-xl-1 {\n    margin-right: 0.25rem !important;\n    margin-left: 0.25rem !important;\n  }\n\n  .mx-xl-2 {\n    margin-right: 0.5rem !important;\n    margin-left: 0.5rem !important;\n  }\n\n  .mx-xl-3 {\n    margin-right: 1rem !important;\n    margin-left: 1rem !important;\n  }\n\n  .mx-xl-4 {\n    margin-right: 1.5rem !important;\n    margin-left: 1.5rem !important;\n  }\n\n  .mx-xl-5 {\n    margin-right: 3rem !important;\n    margin-left: 3rem !important;\n  }\n\n  .mx-xl-auto {\n    margin-right: auto !important;\n    margin-left: auto !important;\n  }\n\n  .my-xl-0 {\n    margin-top: 0 !important;\n    margin-bottom: 0 !important;\n  }\n\n  .my-xl-1 {\n    margin-top: 0.25rem !important;\n    margin-bottom: 0.25rem !important;\n  }\n\n  .my-xl-2 {\n    margin-top: 0.5rem !important;\n    margin-bottom: 0.5rem !important;\n  }\n\n  .my-xl-3 {\n    margin-top: 1rem !important;\n    margin-bottom: 1rem !important;\n  }\n\n  .my-xl-4 {\n    margin-top: 1.5rem !important;\n    margin-bottom: 1.5rem !important;\n  }\n\n  .my-xl-5 {\n    margin-top: 3rem !important;\n    margin-bottom: 3rem !important;\n  }\n\n  .my-xl-auto {\n    margin-top: auto !important;\n    margin-bottom: auto !important;\n  }\n\n  .mt-xl-0 {\n    margin-top: 0 !important;\n  }\n\n  .mt-xl-1 {\n    margin-top: 0.25rem !important;\n  }\n\n  .mt-xl-2 {\n    margin-top: 0.5rem !important;\n  }\n\n  .mt-xl-3 {\n    margin-top: 1rem !important;\n  }\n\n  .mt-xl-4 {\n    margin-top: 1.5rem !important;\n  }\n\n  .mt-xl-5 {\n    margin-top: 3rem !important;\n  }\n\n  .mt-xl-auto {\n    margin-top: auto !important;\n  }\n\n  .me-xl-0 {\n    margin-right: 0 !important;\n  }\n\n  .me-xl-1 {\n    margin-right: 0.25rem !important;\n  }\n\n  .me-xl-2 {\n    margin-right: 0.5rem !important;\n  }\n\n  .me-xl-3 {\n    margin-right: 1rem !important;\n  }\n\n  .me-xl-4 {\n    margin-right: 1.5rem !important;\n  }\n\n  .me-xl-5 {\n    margin-right: 3rem !important;\n  }\n\n  .me-xl-auto {\n    margin-right: auto !important;\n  }\n\n  .mb-xl-0 {\n    margin-bottom: 0 !important;\n  }\n\n  .mb-xl-1 {\n    margin-bottom: 0.25rem !important;\n  }\n\n  .mb-xl-2 {\n    margin-bottom: 0.5rem !important;\n  }\n\n  .mb-xl-3 {\n    margin-bottom: 1rem !important;\n  }\n\n  .mb-xl-4 {\n    margin-bottom: 1.5rem !important;\n  }\n\n  .mb-xl-5 {\n    margin-bottom: 3rem !important;\n  }\n\n  .mb-xl-auto {\n    margin-bottom: auto !important;\n  }\n\n  .ms-xl-0 {\n    margin-left: 0 !important;\n  }\n\n  .ms-xl-1 {\n    margin-left: 0.25rem !important;\n  }\n\n  .ms-xl-2 {\n    margin-left: 0.5rem !important;\n  }\n\n  .ms-xl-3 {\n    margin-left: 1rem !important;\n  }\n\n  .ms-xl-4 {\n    margin-left: 1.5rem !important;\n  }\n\n  .ms-xl-5 {\n    margin-left: 3rem !important;\n  }\n\n  .ms-xl-auto {\n    margin-left: auto !important;\n  }\n\n  .p-xl-0 {\n    padding: 0 !important;\n  }\n\n  .p-xl-1 {\n    padding: 0.25rem !important;\n  }\n\n  .p-xl-2 {\n    padding: 0.5rem !important;\n  }\n\n  .p-xl-3 {\n    padding: 1rem !important;\n  }\n\n  .p-xl-4 {\n    padding: 1.5rem !important;\n  }\n\n  .p-xl-5 {\n    padding: 3rem !important;\n  }\n\n  .px-xl-0 {\n    padding-right: 0 !important;\n    padding-left: 0 !important;\n  }\n\n  .px-xl-1 {\n    padding-right: 0.25rem !important;\n    padding-left: 0.25rem !important;\n  }\n\n  .px-xl-2 {\n    padding-right: 0.5rem !important;\n    padding-left: 0.5rem !important;\n  }\n\n  .px-xl-3 {\n    padding-right: 1rem !important;\n    padding-left: 1rem !important;\n  }\n\n  .px-xl-4 {\n    padding-right: 1.5rem !important;\n    padding-left: 1.5rem !important;\n  }\n\n  .px-xl-5 {\n    padding-right: 3rem !important;\n    padding-left: 3rem !important;\n  }\n\n  .py-xl-0 {\n    padding-top: 0 !important;\n    padding-bottom: 0 !important;\n  }\n\n  .py-xl-1 {\n    padding-top: 0.25rem !important;\n    padding-bottom: 0.25rem !important;\n  }\n\n  .py-xl-2 {\n    padding-top: 0.5rem !important;\n    padding-bottom: 0.5rem !important;\n  }\n\n  .py-xl-3 {\n    padding-top: 1rem !important;\n    padding-bottom: 1rem !important;\n  }\n\n  .py-xl-4 {\n    padding-top: 1.5rem !important;\n    padding-bottom: 1.5rem !important;\n  }\n\n  .py-xl-5 {\n    padding-top: 3rem !important;\n    padding-bottom: 3rem !important;\n  }\n\n  .pt-xl-0 {\n    padding-top: 0 !important;\n  }\n\n  .pt-xl-1 {\n    padding-top: 0.25rem !important;\n  }\n\n  .pt-xl-2 {\n    padding-top: 0.5rem !important;\n  }\n\n  .pt-xl-3 {\n    padding-top: 1rem !important;\n  }\n\n  .pt-xl-4 {\n    padding-top: 1.5rem !important;\n  }\n\n  .pt-xl-5 {\n    padding-top: 3rem !important;\n  }\n\n  .pe-xl-0 {\n    padding-right: 0 !important;\n  }\n\n  .pe-xl-1 {\n    padding-right: 0.25rem !important;\n  }\n\n  .pe-xl-2 {\n    padding-right: 0.5rem !important;\n  }\n\n  .pe-xl-3 {\n    padding-right: 1rem !important;\n  }\n\n  .pe-xl-4 {\n    padding-right: 1.5rem !important;\n  }\n\n  .pe-xl-5 {\n    padding-right: 3rem !important;\n  }\n\n  .pb-xl-0 {\n    padding-bottom: 0 !important;\n  }\n\n  .pb-xl-1 {\n    padding-bottom: 0.25rem !important;\n  }\n\n  .pb-xl-2 {\n    padding-bottom: 0.5rem !important;\n  }\n\n  .pb-xl-3 {\n    padding-bottom: 1rem !important;\n  }\n\n  .pb-xl-4 {\n    padding-bottom: 1.5rem !important;\n  }\n\n  .pb-xl-5 {\n    padding-bottom: 3rem !important;\n  }\n\n  .ps-xl-0 {\n    padding-left: 0 !important;\n  }\n\n  .ps-xl-1 {\n    padding-left: 0.25rem !important;\n  }\n\n  .ps-xl-2 {\n    padding-left: 0.5rem !important;\n  }\n\n  .ps-xl-3 {\n    padding-left: 1rem !important;\n  }\n\n  .ps-xl-4 {\n    padding-left: 1.5rem !important;\n  }\n\n  .ps-xl-5 {\n    padding-left: 3rem !important;\n  }\n\n  .text-xl-start {\n    text-align: left !important;\n  }\n\n  .text-xl-end {\n    text-align: right !important;\n  }\n\n  .text-xl-center {\n    text-align: center !important;\n  }\n}\n@media (min-width: 1400px) {\n  .float-xxl-start {\n    float: left !important;\n  }\n\n  .float-xxl-end {\n    float: right !important;\n  }\n\n  .float-xxl-none {\n    float: none !important;\n  }\n\n  .d-xxl-inline {\n    display: inline !important;\n  }\n\n  .d-xxl-inline-block {\n    display: inline-block !important;\n  }\n\n  .d-xxl-block {\n    display: block !important;\n  }\n\n  .d-xxl-grid {\n    display: grid !important;\n  }\n\n  .d-xxl-table {\n    display: table !important;\n  }\n\n  .d-xxl-table-row {\n    display: table-row !important;\n  }\n\n  .d-xxl-table-cell {\n    display: table-cell !important;\n  }\n\n  .d-xxl-flex {\n    display: flex !important;\n  }\n\n  .d-xxl-inline-flex {\n    display: inline-flex !important;\n  }\n\n  .d-xxl-none {\n    display: none !important;\n  }\n\n  .flex-xxl-fill {\n    flex: 1 1 auto !important;\n  }\n\n  .flex-xxl-row {\n    flex-direction: row !important;\n  }\n\n  .flex-xxl-column {\n    flex-direction: column !important;\n  }\n\n  .flex-xxl-row-reverse {\n    flex-direction: row-reverse !important;\n  }\n\n  .flex-xxl-column-reverse {\n    flex-direction: column-reverse !important;\n  }\n\n  .flex-xxl-grow-0 {\n    flex-grow: 0 !important;\n  }\n\n  .flex-xxl-grow-1 {\n    flex-grow: 1 !important;\n  }\n\n  .flex-xxl-shrink-0 {\n    flex-shrink: 0 !important;\n  }\n\n  .flex-xxl-shrink-1 {\n    flex-shrink: 1 !important;\n  }\n\n  .flex-xxl-wrap {\n    flex-wrap: wrap !important;\n  }\n\n  .flex-xxl-nowrap {\n    flex-wrap: nowrap !important;\n  }\n\n  .flex-xxl-wrap-reverse {\n    flex-wrap: wrap-reverse !important;\n  }\n\n  .gap-xxl-0 {\n    gap: 0 !important;\n  }\n\n  .gap-xxl-1 {\n    gap: 0.25rem !important;\n  }\n\n  .gap-xxl-2 {\n    gap: 0.5rem !important;\n  }\n\n  .gap-xxl-3 {\n    gap: 1rem !important;\n  }\n\n  .gap-xxl-4 {\n    gap: 1.5rem !important;\n  }\n\n  .gap-xxl-5 {\n    gap: 3rem !important;\n  }\n\n  .justify-content-xxl-start {\n    justify-content: flex-start !important;\n  }\n\n  .justify-content-xxl-end {\n    justify-content: flex-end !important;\n  }\n\n  .justify-content-xxl-center {\n    justify-content: center !important;\n  }\n\n  .justify-content-xxl-between {\n    justify-content: space-between !important;\n  }\n\n  .justify-content-xxl-around {\n    justify-content: space-around !important;\n  }\n\n  .justify-content-xxl-evenly {\n    justify-content: space-evenly !important;\n  }\n\n  .align-items-xxl-start {\n    align-items: flex-start !important;\n  }\n\n  .align-items-xxl-end {\n    align-items: flex-end !important;\n  }\n\n  .align-items-xxl-center {\n    align-items: center !important;\n  }\n\n  .align-items-xxl-baseline {\n    align-items: baseline !important;\n  }\n\n  .align-items-xxl-stretch {\n    align-items: stretch !important;\n  }\n\n  .align-content-xxl-start {\n    align-content: flex-start !important;\n  }\n\n  .align-content-xxl-end {\n    align-content: flex-end !important;\n  }\n\n  .align-content-xxl-center {\n    align-content: center !important;\n  }\n\n  .align-content-xxl-between {\n    align-content: space-between !important;\n  }\n\n  .align-content-xxl-around {\n    align-content: space-around !important;\n  }\n\n  .align-content-xxl-stretch {\n    align-content: stretch !important;\n  }\n\n  .align-self-xxl-auto {\n    align-self: auto !important;\n  }\n\n  .align-self-xxl-start {\n    align-self: flex-start !important;\n  }\n\n  .align-self-xxl-end {\n    align-self: flex-end !important;\n  }\n\n  .align-self-xxl-center {\n    align-self: center !important;\n  }\n\n  .align-self-xxl-baseline {\n    align-self: baseline !important;\n  }\n\n  .align-self-xxl-stretch {\n    align-self: stretch !important;\n  }\n\n  .order-xxl-first {\n    order: -1 !important;\n  }\n\n  .order-xxl-0 {\n    order: 0 !important;\n  }\n\n  .order-xxl-1 {\n    order: 1 !important;\n  }\n\n  .order-xxl-2 {\n    order: 2 !important;\n  }\n\n  .order-xxl-3 {\n    order: 3 !important;\n  }\n\n  .order-xxl-4 {\n    order: 4 !important;\n  }\n\n  .order-xxl-5 {\n    order: 5 !important;\n  }\n\n  .order-xxl-last {\n    order: 6 !important;\n  }\n\n  .m-xxl-0 {\n    margin: 0 !important;\n  }\n\n  .m-xxl-1 {\n    margin: 0.25rem !important;\n  }\n\n  .m-xxl-2 {\n    margin: 0.5rem !important;\n  }\n\n  .m-xxl-3 {\n    margin: 1rem !important;\n  }\n\n  .m-xxl-4 {\n    margin: 1.5rem !important;\n  }\n\n  .m-xxl-5 {\n    margin: 3rem !important;\n  }\n\n  .m-xxl-auto {\n    margin: auto !important;\n  }\n\n  .mx-xxl-0 {\n    margin-right: 0 !important;\n    margin-left: 0 !important;\n  }\n\n  .mx-xxl-1 {\n    margin-right: 0.25rem !important;\n    margin-left: 0.25rem !important;\n  }\n\n  .mx-xxl-2 {\n    margin-right: 0.5rem !important;\n    margin-left: 0.5rem !important;\n  }\n\n  .mx-xxl-3 {\n    margin-right: 1rem !important;\n    margin-left: 1rem !important;\n  }\n\n  .mx-xxl-4 {\n    margin-right: 1.5rem !important;\n    margin-left: 1.5rem !important;\n  }\n\n  .mx-xxl-5 {\n    margin-right: 3rem !important;\n    margin-left: 3rem !important;\n  }\n\n  .mx-xxl-auto {\n    margin-right: auto !important;\n    margin-left: auto !important;\n  }\n\n  .my-xxl-0 {\n    margin-top: 0 !important;\n    margin-bottom: 0 !important;\n  }\n\n  .my-xxl-1 {\n    margin-top: 0.25rem !important;\n    margin-bottom: 0.25rem !important;\n  }\n\n  .my-xxl-2 {\n    margin-top: 0.5rem !important;\n    margin-bottom: 0.5rem !important;\n  }\n\n  .my-xxl-3 {\n    margin-top: 1rem !important;\n    margin-bottom: 1rem !important;\n  }\n\n  .my-xxl-4 {\n    margin-top: 1.5rem !important;\n    margin-bottom: 1.5rem !important;\n  }\n\n  .my-xxl-5 {\n    margin-top: 3rem !important;\n    margin-bottom: 3rem !important;\n  }\n\n  .my-xxl-auto {\n    margin-top: auto !important;\n    margin-bottom: auto !important;\n  }\n\n  .mt-xxl-0 {\n    margin-top: 0 !important;\n  }\n\n  .mt-xxl-1 {\n    margin-top: 0.25rem !important;\n  }\n\n  .mt-xxl-2 {\n    margin-top: 0.5rem !important;\n  }\n\n  .mt-xxl-3 {\n    margin-top: 1rem !important;\n  }\n\n  .mt-xxl-4 {\n    margin-top: 1.5rem !important;\n  }\n\n  .mt-xxl-5 {\n    margin-top: 3rem !important;\n  }\n\n  .mt-xxl-auto {\n    margin-top: auto !important;\n  }\n\n  .me-xxl-0 {\n    margin-right: 0 !important;\n  }\n\n  .me-xxl-1 {\n    margin-right: 0.25rem !important;\n  }\n\n  .me-xxl-2 {\n    margin-right: 0.5rem !important;\n  }\n\n  .me-xxl-3 {\n    margin-right: 1rem !important;\n  }\n\n  .me-xxl-4 {\n    margin-right: 1.5rem !important;\n  }\n\n  .me-xxl-5 {\n    margin-right: 3rem !important;\n  }\n\n  .me-xxl-auto {\n    margin-right: auto !important;\n  }\n\n  .mb-xxl-0 {\n    margin-bottom: 0 !important;\n  }\n\n  .mb-xxl-1 {\n    margin-bottom: 0.25rem !important;\n  }\n\n  .mb-xxl-2 {\n    margin-bottom: 0.5rem !important;\n  }\n\n  .mb-xxl-3 {\n    margin-bottom: 1rem !important;\n  }\n\n  .mb-xxl-4 {\n    margin-bottom: 1.5rem !important;\n  }\n\n  .mb-xxl-5 {\n    margin-bottom: 3rem !important;\n  }\n\n  .mb-xxl-auto {\n    margin-bottom: auto !important;\n  }\n\n  .ms-xxl-0 {\n    margin-left: 0 !important;\n  }\n\n  .ms-xxl-1 {\n    margin-left: 0.25rem !important;\n  }\n\n  .ms-xxl-2 {\n    margin-left: 0.5rem !important;\n  }\n\n  .ms-xxl-3 {\n    margin-left: 1rem !important;\n  }\n\n  .ms-xxl-4 {\n    margin-left: 1.5rem !important;\n  }\n\n  .ms-xxl-5 {\n    margin-left: 3rem !important;\n  }\n\n  .ms-xxl-auto {\n    margin-left: auto !important;\n  }\n\n  .p-xxl-0 {\n    padding: 0 !important;\n  }\n\n  .p-xxl-1 {\n    padding: 0.25rem !important;\n  }\n\n  .p-xxl-2 {\n    padding: 0.5rem !important;\n  }\n\n  .p-xxl-3 {\n    padding: 1rem !important;\n  }\n\n  .p-xxl-4 {\n    padding: 1.5rem !important;\n  }\n\n  .p-xxl-5 {\n    padding: 3rem !important;\n  }\n\n  .px-xxl-0 {\n    padding-right: 0 !important;\n    padding-left: 0 !important;\n  }\n\n  .px-xxl-1 {\n    padding-right: 0.25rem !important;\n    padding-left: 0.25rem !important;\n  }\n\n  .px-xxl-2 {\n    padding-right: 0.5rem !important;\n    padding-left: 0.5rem !important;\n  }\n\n  .px-xxl-3 {\n    padding-right: 1rem !important;\n    padding-left: 1rem !important;\n  }\n\n  .px-xxl-4 {\n    padding-right: 1.5rem !important;\n    padding-left: 1.5rem !important;\n  }\n\n  .px-xxl-5 {\n    padding-right: 3rem !important;\n    padding-left: 3rem !important;\n  }\n\n  .py-xxl-0 {\n    padding-top: 0 !important;\n    padding-bottom: 0 !important;\n  }\n\n  .py-xxl-1 {\n    padding-top: 0.25rem !important;\n    padding-bottom: 0.25rem !important;\n  }\n\n  .py-xxl-2 {\n    padding-top: 0.5rem !important;\n    padding-bottom: 0.5rem !important;\n  }\n\n  .py-xxl-3 {\n    padding-top: 1rem !important;\n    padding-bottom: 1rem !important;\n  }\n\n  .py-xxl-4 {\n    padding-top: 1.5rem !important;\n    padding-bottom: 1.5rem !important;\n  }\n\n  .py-xxl-5 {\n    padding-top: 3rem !important;\n    padding-bottom: 3rem !important;\n  }\n\n  .pt-xxl-0 {\n    padding-top: 0 !important;\n  }\n\n  .pt-xxl-1 {\n    padding-top: 0.25rem !important;\n  }\n\n  .pt-xxl-2 {\n    padding-top: 0.5rem !important;\n  }\n\n  .pt-xxl-3 {\n    padding-top: 1rem !important;\n  }\n\n  .pt-xxl-4 {\n    padding-top: 1.5rem !important;\n  }\n\n  .pt-xxl-5 {\n    padding-top: 3rem !important;\n  }\n\n  .pe-xxl-0 {\n    padding-right: 0 !important;\n  }\n\n  .pe-xxl-1 {\n    padding-right: 0.25rem !important;\n  }\n\n  .pe-xxl-2 {\n    padding-right: 0.5rem !important;\n  }\n\n  .pe-xxl-3 {\n    padding-right: 1rem !important;\n  }\n\n  .pe-xxl-4 {\n    padding-right: 1.5rem !important;\n  }\n\n  .pe-xxl-5 {\n    padding-right: 3rem !important;\n  }\n\n  .pb-xxl-0 {\n    padding-bottom: 0 !important;\n  }\n\n  .pb-xxl-1 {\n    padding-bottom: 0.25rem !important;\n  }\n\n  .pb-xxl-2 {\n    padding-bottom: 0.5rem !important;\n  }\n\n  .pb-xxl-3 {\n    padding-bottom: 1rem !important;\n  }\n\n  .pb-xxl-4 {\n    padding-bottom: 1.5rem !important;\n  }\n\n  .pb-xxl-5 {\n    padding-bottom: 3rem !important;\n  }\n\n  .ps-xxl-0 {\n    padding-left: 0 !important;\n  }\n\n  .ps-xxl-1 {\n    padding-left: 0.25rem !important;\n  }\n\n  .ps-xxl-2 {\n    padding-left: 0.5rem !important;\n  }\n\n  .ps-xxl-3 {\n    padding-left: 1rem !important;\n  }\n\n  .ps-xxl-4 {\n    padding-left: 1.5rem !important;\n  }\n\n  .ps-xxl-5 {\n    padding-left: 3rem !important;\n  }\n\n  .text-xxl-start {\n    text-align: left !important;\n  }\n\n  .text-xxl-end {\n    text-align: right !important;\n  }\n\n  .text-xxl-center {\n    text-align: center !important;\n  }\n}\n@media (min-width: 1200px) {\n  .fs-1 {\n    font-size: 2.5rem !important;\n  }\n\n  .fs-2 {\n    font-size: 2rem !important;\n  }\n\n  .fs-3 {\n    font-size: 1.75rem !important;\n  }\n\n  .fs-4 {\n    font-size: 1.5rem !important;\n  }\n}\n@media print {\n  .d-print-inline {\n    display: inline !important;\n  }\n\n  .d-print-inline-block {\n    display: inline-block !important;\n  }\n\n  .d-print-block {\n    display: block !important;\n  }\n\n  .d-print-grid {\n    display: grid !important;\n  }\n\n  .d-print-table {\n    display: table !important;\n  }\n\n  .d-print-table-row {\n    display: table-row !important;\n  }\n\n  .d-print-table-cell {\n    display: table-cell !important;\n  }\n\n  .d-print-flex {\n    display: flex !important;\n  }\n\n  .d-print-inline-flex {\n    display: inline-flex !important;\n  }\n\n  .d-print-none {\n    display: none !important;\n  }\n}\n\n/*# sourceMappingURL=bootstrap.css.map */"
  },
  {
    "path": "public/css/fatrat.css",
    "content": ".frc-option-add-edit table p {\n    color: #838383;\n    font-size: 12px;\n}\n.spider-tab-content table p {\n    color: #838383;\n    font-size: 12px;\n}\n.spider-tab-content p {\n    color: #838383;\n    font-size: 12px;\n}\n.todo-and-author-class li {\n    color: #336600;\n    font-size: 13px;\n}\n.frc-appreciate-class li {\n    float: left; font-size: 12px; width: 150px;\n    color: #0027ff;\n}\n.p-tips-style {\n    color: #9e9d24;\n    font-size: 12px;\n    padding-top: 5px;\n}\n.p-tips-style-color1 {\n    color: #3300aa;\n    font-size: 12px;\n    padding-top: 5px;\n}\n.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear};fa-spin{0%{-webkit-transform:rotate(0deg);\n    transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);\n    transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}\nul {\n    padding-left: 0;\n}"
  },
  {
    "path": "public/js/bootstrap.js",
    "content": "/*!\n  * Bootstrap v5.0.2 (https://getbootstrap.com/)\n  * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core')) :\n  typeof define === 'function' && define.amd ? define(['@popperjs/core'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory(global.Popper));\n}(this, (function (Popper) { 'use strict';\n\n  function _interopNamespace(e) {\n    if (e && e.__esModule) return e;\n    var n = Object.create(null);\n    if (e) {\n      Object.keys(e).forEach(function (k) {\n        if (k !== 'default') {\n          var d = Object.getOwnPropertyDescriptor(e, k);\n          Object.defineProperty(n, k, d.get ? d : {\n            enumerable: true,\n            get: function () {\n              return e[k];\n            }\n          });\n        }\n      });\n    }\n    n['default'] = e;\n    return Object.freeze(n);\n  }\n\n  var Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): dom/selector-engine.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  const NODE_TEXT = 3;\n  const SelectorEngine = {\n    find(selector, element = document.documentElement) {\n      return [].concat(...Element.prototype.querySelectorAll.call(element, selector));\n    },\n\n    findOne(selector, element = document.documentElement) {\n      return Element.prototype.querySelector.call(element, selector);\n    },\n\n    children(element, selector) {\n      return [].concat(...element.children).filter(child => child.matches(selector));\n    },\n\n    parents(element, selector) {\n      const parents = [];\n      let ancestor = element.parentNode;\n\n      while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) {\n        if (ancestor.matches(selector)) {\n          parents.push(ancestor);\n        }\n\n        ancestor = ancestor.parentNode;\n      }\n\n      return parents;\n    },\n\n    prev(element, selector) {\n      let previous = element.previousElementSibling;\n\n      while (previous) {\n        if (previous.matches(selector)) {\n          return [previous];\n        }\n\n        previous = previous.previousElementSibling;\n      }\n\n      return [];\n    },\n\n    next(element, selector) {\n      let next = element.nextElementSibling;\n\n      while (next) {\n        if (next.matches(selector)) {\n          return [next];\n        }\n\n        next = next.nextElementSibling;\n      }\n\n      return [];\n    }\n\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): util/index.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n\n  const MAX_UID = 1000000;\n  const MILLISECONDS_MULTIPLIER = 1000;\n  const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n\n  const toType = obj => {\n    if (obj === null || obj === undefined) {\n      return `${obj}`;\n    }\n\n    return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase();\n  };\n  /**\n   * --------------------------------------------------------------------------\n   * Public Util Api\n   * --------------------------------------------------------------------------\n   */\n\n\n  const getUID = prefix => {\n    do {\n      prefix += Math.floor(Math.random() * MAX_UID);\n    } while (document.getElementById(prefix));\n\n    return prefix;\n  };\n\n  const getSelector = element => {\n    let selector = element.getAttribute('data-bs-target');\n\n    if (!selector || selector === '#') {\n      let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,\n      // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n      // `document.querySelector` will rightfully complain it is invalid.\n      // See https://github.com/twbs/bootstrap/issues/32273\n\n      if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {\n        return null;\n      } // Just in case some CMS puts out a full URL with the anchor appended\n\n\n      if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {\n        hrefAttr = `#${hrefAttr.split('#')[1]}`;\n      }\n\n      selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;\n    }\n\n    return selector;\n  };\n\n  const getSelectorFromElement = element => {\n    const selector = getSelector(element);\n\n    if (selector) {\n      return document.querySelector(selector) ? selector : null;\n    }\n\n    return null;\n  };\n\n  const getElementFromSelector = element => {\n    const selector = getSelector(element);\n    return selector ? document.querySelector(selector) : null;\n  };\n\n  const getTransitionDurationFromElement = element => {\n    if (!element) {\n      return 0;\n    } // Get transition-duration of the element\n\n\n    let {\n      transitionDuration,\n      transitionDelay\n    } = window.getComputedStyle(element);\n    const floatTransitionDuration = Number.parseFloat(transitionDuration);\n    const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found\n\n    if (!floatTransitionDuration && !floatTransitionDelay) {\n      return 0;\n    } // If multiple durations are defined, take the first\n\n\n    transitionDuration = transitionDuration.split(',')[0];\n    transitionDelay = transitionDelay.split(',')[0];\n    return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n  };\n\n  const triggerTransitionEnd = element => {\n    element.dispatchEvent(new Event(TRANSITION_END));\n  };\n\n  const isElement = obj => {\n    if (!obj || typeof obj !== 'object') {\n      return false;\n    }\n\n    if (typeof obj.jquery !== 'undefined') {\n      obj = obj[0];\n    }\n\n    return typeof obj.nodeType !== 'undefined';\n  };\n\n  const getElement = obj => {\n    if (isElement(obj)) {\n      // it's a jQuery object or a node element\n      return obj.jquery ? obj[0] : obj;\n    }\n\n    if (typeof obj === 'string' && obj.length > 0) {\n      return SelectorEngine.findOne(obj);\n    }\n\n    return null;\n  };\n\n  const typeCheckConfig = (componentName, config, configTypes) => {\n    Object.keys(configTypes).forEach(property => {\n      const expectedTypes = configTypes[property];\n      const value = config[property];\n      const valueType = value && isElement(value) ? 'element' : toType(value);\n\n      if (!new RegExp(expectedTypes).test(valueType)) {\n        throw new TypeError(`${componentName.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`);\n      }\n    });\n  };\n\n  const isVisible = element => {\n    if (!isElement(element) || element.getClientRects().length === 0) {\n      return false;\n    }\n\n    return getComputedStyle(element).getPropertyValue('visibility') === 'visible';\n  };\n\n  const isDisabled = element => {\n    if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n      return true;\n    }\n\n    if (element.classList.contains('disabled')) {\n      return true;\n    }\n\n    if (typeof element.disabled !== 'undefined') {\n      return element.disabled;\n    }\n\n    return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';\n  };\n\n  const findShadowRoot = element => {\n    if (!document.documentElement.attachShadow) {\n      return null;\n    } // Can find the shadow root otherwise it'll return the document\n\n\n    if (typeof element.getRootNode === 'function') {\n      const root = element.getRootNode();\n      return root instanceof ShadowRoot ? root : null;\n    }\n\n    if (element instanceof ShadowRoot) {\n      return element;\n    } // when we don't find a shadow root\n\n\n    if (!element.parentNode) {\n      return null;\n    }\n\n    return findShadowRoot(element.parentNode);\n  };\n\n  const noop = () => {};\n\n  const reflow = element => element.offsetHeight;\n\n  const getjQuery = () => {\n    const {\n      jQuery\n    } = window;\n\n    if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n      return jQuery;\n    }\n\n    return null;\n  };\n\n  const DOMContentLoadedCallbacks = [];\n\n  const onDOMContentLoaded = callback => {\n    if (document.readyState === 'loading') {\n      // add listener on the first call when the document is in loading state\n      if (!DOMContentLoadedCallbacks.length) {\n        document.addEventListener('DOMContentLoaded', () => {\n          DOMContentLoadedCallbacks.forEach(callback => callback());\n        });\n      }\n\n      DOMContentLoadedCallbacks.push(callback);\n    } else {\n      callback();\n    }\n  };\n\n  const isRTL = () => document.documentElement.dir === 'rtl';\n\n  const defineJQueryPlugin = plugin => {\n    onDOMContentLoaded(() => {\n      const $ = getjQuery();\n      /* istanbul ignore if */\n\n      if ($) {\n        const name = plugin.NAME;\n        const JQUERY_NO_CONFLICT = $.fn[name];\n        $.fn[name] = plugin.jQueryInterface;\n        $.fn[name].Constructor = plugin;\n\n        $.fn[name].noConflict = () => {\n          $.fn[name] = JQUERY_NO_CONFLICT;\n          return plugin.jQueryInterface;\n        };\n      }\n    });\n  };\n\n  const execute = callback => {\n    if (typeof callback === 'function') {\n      callback();\n    }\n  };\n\n  const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n    if (!waitForTransition) {\n      execute(callback);\n      return;\n    }\n\n    const durationPadding = 5;\n    const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;\n    let called = false;\n\n    const handler = ({\n      target\n    }) => {\n      if (target !== transitionElement) {\n        return;\n      }\n\n      called = true;\n      transitionElement.removeEventListener(TRANSITION_END, handler);\n      execute(callback);\n    };\n\n    transitionElement.addEventListener(TRANSITION_END, handler);\n    setTimeout(() => {\n      if (!called) {\n        triggerTransitionEnd(transitionElement);\n      }\n    }, emulatedDuration);\n  };\n  /**\n   * Return the previous/next element of a list.\n   *\n   * @param {array} list    The list of elements\n   * @param activeElement   The active element\n   * @param shouldGetNext   Choose to get next or previous element\n   * @param isCycleAllowed\n   * @return {Element|elem} The proper element\n   */\n\n\n  const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n    let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed\n\n    if (index === -1) {\n      return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];\n    }\n\n    const listLength = list.length;\n    index += shouldGetNext ? 1 : -1;\n\n    if (isCycleAllowed) {\n      index = (index + listLength) % listLength;\n    }\n\n    return list[Math.max(0, Math.min(index, listLength - 1))];\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): dom/event-handler.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const namespaceRegex = /[^.]*(?=\\..*)\\.|.*/;\n  const stripNameRegex = /\\..*/;\n  const stripUidRegex = /::\\d+$/;\n  const eventRegistry = {}; // Events storage\n\n  let uidEvent = 1;\n  const customEvents = {\n    mouseenter: 'mouseover',\n    mouseleave: 'mouseout'\n  };\n  const customEventsRegex = /^(mouseenter|mouseleave)/i;\n  const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']);\n  /**\n   * ------------------------------------------------------------------------\n   * Private methods\n   * ------------------------------------------------------------------------\n   */\n\n  function getUidEvent(element, uid) {\n    return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++;\n  }\n\n  function getEvent(element) {\n    const uid = getUidEvent(element);\n    element.uidEvent = uid;\n    eventRegistry[uid] = eventRegistry[uid] || {};\n    return eventRegistry[uid];\n  }\n\n  function bootstrapHandler(element, fn) {\n    return function handler(event) {\n      event.delegateTarget = element;\n\n      if (handler.oneOff) {\n        EventHandler.off(element, event.type, fn);\n      }\n\n      return fn.apply(element, [event]);\n    };\n  }\n\n  function bootstrapDelegationHandler(element, selector, fn) {\n    return function handler(event) {\n      const domElements = element.querySelectorAll(selector);\n\n      for (let {\n        target\n      } = event; target && target !== this; target = target.parentNode) {\n        for (let i = domElements.length; i--;) {\n          if (domElements[i] === target) {\n            event.delegateTarget = target;\n\n            if (handler.oneOff) {\n              // eslint-disable-next-line unicorn/consistent-destructuring\n              EventHandler.off(element, event.type, selector, fn);\n            }\n\n            return fn.apply(target, [event]);\n          }\n        }\n      } // To please ESLint\n\n\n      return null;\n    };\n  }\n\n  function findHandler(events, handler, delegationSelector = null) {\n    const uidEventList = Object.keys(events);\n\n    for (let i = 0, len = uidEventList.length; i < len; i++) {\n      const event = events[uidEventList[i]];\n\n      if (event.originalHandler === handler && event.delegationSelector === delegationSelector) {\n        return event;\n      }\n    }\n\n    return null;\n  }\n\n  function normalizeParams(originalTypeEvent, handler, delegationFn) {\n    const delegation = typeof handler === 'string';\n    const originalHandler = delegation ? delegationFn : handler;\n    let typeEvent = getTypeEvent(originalTypeEvent);\n    const isNative = nativeEvents.has(typeEvent);\n\n    if (!isNative) {\n      typeEvent = originalTypeEvent;\n    }\n\n    return [delegation, originalHandler, typeEvent];\n  }\n\n  function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {\n    if (typeof originalTypeEvent !== 'string' || !element) {\n      return;\n    }\n\n    if (!handler) {\n      handler = delegationFn;\n      delegationFn = null;\n    } // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n    // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n\n\n    if (customEventsRegex.test(originalTypeEvent)) {\n      const wrapFn = fn => {\n        return function (event) {\n          if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) {\n            return fn.call(this, event);\n          }\n        };\n      };\n\n      if (delegationFn) {\n        delegationFn = wrapFn(delegationFn);\n      } else {\n        handler = wrapFn(handler);\n      }\n    }\n\n    const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn);\n    const events = getEvent(element);\n    const handlers = events[typeEvent] || (events[typeEvent] = {});\n    const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null);\n\n    if (previousFn) {\n      previousFn.oneOff = previousFn.oneOff && oneOff;\n      return;\n    }\n\n    const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''));\n    const fn = delegation ? bootstrapDelegationHandler(element, handler, delegationFn) : bootstrapHandler(element, handler);\n    fn.delegationSelector = delegation ? handler : null;\n    fn.originalHandler = originalHandler;\n    fn.oneOff = oneOff;\n    fn.uidEvent = uid;\n    handlers[uid] = fn;\n    element.addEventListener(typeEvent, fn, delegation);\n  }\n\n  function removeHandler(element, events, typeEvent, handler, delegationSelector) {\n    const fn = findHandler(events[typeEvent], handler, delegationSelector);\n\n    if (!fn) {\n      return;\n    }\n\n    element.removeEventListener(typeEvent, fn, Boolean(delegationSelector));\n    delete events[typeEvent][fn.uidEvent];\n  }\n\n  function removeNamespacedHandlers(element, events, typeEvent, namespace) {\n    const storeElementEvent = events[typeEvent] || {};\n    Object.keys(storeElementEvent).forEach(handlerKey => {\n      if (handlerKey.includes(namespace)) {\n        const event = storeElementEvent[handlerKey];\n        removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector);\n      }\n    });\n  }\n\n  function getTypeEvent(event) {\n    // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n    event = event.replace(stripNameRegex, '');\n    return customEvents[event] || event;\n  }\n\n  const EventHandler = {\n    on(element, event, handler, delegationFn) {\n      addHandler(element, event, handler, delegationFn, false);\n    },\n\n    one(element, event, handler, delegationFn) {\n      addHandler(element, event, handler, delegationFn, true);\n    },\n\n    off(element, originalTypeEvent, handler, delegationFn) {\n      if (typeof originalTypeEvent !== 'string' || !element) {\n        return;\n      }\n\n      const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn);\n      const inNamespace = typeEvent !== originalTypeEvent;\n      const events = getEvent(element);\n      const isNamespace = originalTypeEvent.startsWith('.');\n\n      if (typeof originalHandler !== 'undefined') {\n        // Simplest case: handler is passed, remove that listener ONLY.\n        if (!events || !events[typeEvent]) {\n          return;\n        }\n\n        removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null);\n        return;\n      }\n\n      if (isNamespace) {\n        Object.keys(events).forEach(elementEvent => {\n          removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1));\n        });\n      }\n\n      const storeElementEvent = events[typeEvent] || {};\n      Object.keys(storeElementEvent).forEach(keyHandlers => {\n        const handlerKey = keyHandlers.replace(stripUidRegex, '');\n\n        if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n          const event = storeElementEvent[keyHandlers];\n          removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector);\n        }\n      });\n    },\n\n    trigger(element, event, args) {\n      if (typeof event !== 'string' || !element) {\n        return null;\n      }\n\n      const $ = getjQuery();\n      const typeEvent = getTypeEvent(event);\n      const inNamespace = event !== typeEvent;\n      const isNative = nativeEvents.has(typeEvent);\n      let jQueryEvent;\n      let bubbles = true;\n      let nativeDispatch = true;\n      let defaultPrevented = false;\n      let evt = null;\n\n      if (inNamespace && $) {\n        jQueryEvent = $.Event(event, args);\n        $(element).trigger(jQueryEvent);\n        bubbles = !jQueryEvent.isPropagationStopped();\n        nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();\n        defaultPrevented = jQueryEvent.isDefaultPrevented();\n      }\n\n      if (isNative) {\n        evt = document.createEvent('HTMLEvents');\n        evt.initEvent(typeEvent, bubbles, true);\n      } else {\n        evt = new CustomEvent(event, {\n          bubbles,\n          cancelable: true\n        });\n      } // merge custom information in our event\n\n\n      if (typeof args !== 'undefined') {\n        Object.keys(args).forEach(key => {\n          Object.defineProperty(evt, key, {\n            get() {\n              return args[key];\n            }\n\n          });\n        });\n      }\n\n      if (defaultPrevented) {\n        evt.preventDefault();\n      }\n\n      if (nativeDispatch) {\n        element.dispatchEvent(evt);\n      }\n\n      if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {\n        jQueryEvent.preventDefault();\n      }\n\n      return evt;\n    }\n\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): dom/data.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n  const elementMap = new Map();\n  var Data = {\n    set(element, key, instance) {\n      if (!elementMap.has(element)) {\n        elementMap.set(element, new Map());\n      }\n\n      const instanceMap = elementMap.get(element); // make it clear we only want one instance per element\n      // can be removed later when multiple key/instances are fine to be used\n\n      if (!instanceMap.has(key) && instanceMap.size !== 0) {\n        // eslint-disable-next-line no-console\n        console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`);\n        return;\n      }\n\n      instanceMap.set(key, instance);\n    },\n\n    get(element, key) {\n      if (elementMap.has(element)) {\n        return elementMap.get(element).get(key) || null;\n      }\n\n      return null;\n    },\n\n    remove(element, key) {\n      if (!elementMap.has(element)) {\n        return;\n      }\n\n      const instanceMap = elementMap.get(element);\n      instanceMap.delete(key); // free up element references if there are no instances left for an element\n\n      if (instanceMap.size === 0) {\n        elementMap.delete(element);\n      }\n    }\n\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): base-component.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const VERSION = '5.0.2';\n\n  class BaseComponent {\n    constructor(element) {\n      element = getElement(element);\n\n      if (!element) {\n        return;\n      }\n\n      this._element = element;\n      Data.set(this._element, this.constructor.DATA_KEY, this);\n    }\n\n    dispose() {\n      Data.remove(this._element, this.constructor.DATA_KEY);\n      EventHandler.off(this._element, this.constructor.EVENT_KEY);\n      Object.getOwnPropertyNames(this).forEach(propertyName => {\n        this[propertyName] = null;\n      });\n    }\n\n    _queueCallback(callback, element, isAnimated = true) {\n      executeAfterTransition(callback, element, isAnimated);\n    }\n    /** Static */\n\n\n    static getInstance(element) {\n      return Data.get(element, this.DATA_KEY);\n    }\n\n    static getOrCreateInstance(element, config = {}) {\n      return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);\n    }\n\n    static get VERSION() {\n      return VERSION;\n    }\n\n    static get NAME() {\n      throw new Error('You have to implement the static method \"NAME\", for each component!');\n    }\n\n    static get DATA_KEY() {\n      return `bs.${this.NAME}`;\n    }\n\n    static get EVENT_KEY() {\n      return `.${this.DATA_KEY}`;\n    }\n\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): alert.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$c = 'alert';\n  const DATA_KEY$b = 'bs.alert';\n  const EVENT_KEY$b = `.${DATA_KEY$b}`;\n  const DATA_API_KEY$8 = '.data-api';\n  const SELECTOR_DISMISS = '[data-bs-dismiss=\"alert\"]';\n  const EVENT_CLOSE = `close${EVENT_KEY$b}`;\n  const EVENT_CLOSED = `closed${EVENT_KEY$b}`;\n  const EVENT_CLICK_DATA_API$7 = `click${EVENT_KEY$b}${DATA_API_KEY$8}`;\n  const CLASS_NAME_ALERT = 'alert';\n  const CLASS_NAME_FADE$6 = 'fade';\n  const CLASS_NAME_SHOW$9 = 'show';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Alert extends BaseComponent {\n    // Getters\n    static get NAME() {\n      return NAME$c;\n    } // Public\n\n\n    close(element) {\n      const rootElement = element ? this._getRootElement(element) : this._element;\n\n      const customEvent = this._triggerCloseEvent(rootElement);\n\n      if (customEvent === null || customEvent.defaultPrevented) {\n        return;\n      }\n\n      this._removeElement(rootElement);\n    } // Private\n\n\n    _getRootElement(element) {\n      return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`);\n    }\n\n    _triggerCloseEvent(element) {\n      return EventHandler.trigger(element, EVENT_CLOSE);\n    }\n\n    _removeElement(element) {\n      element.classList.remove(CLASS_NAME_SHOW$9);\n      const isAnimated = element.classList.contains(CLASS_NAME_FADE$6);\n\n      this._queueCallback(() => this._destroyElement(element), element, isAnimated);\n    }\n\n    _destroyElement(element) {\n      element.remove();\n      EventHandler.trigger(element, EVENT_CLOSED);\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Alert.getOrCreateInstance(this);\n\n        if (config === 'close') {\n          data[config](this);\n        }\n      });\n    }\n\n    static handleDismiss(alertInstance) {\n      return function (event) {\n        if (event) {\n          event.preventDefault();\n        }\n\n        alertInstance.close(this);\n      };\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_DISMISS, Alert.handleDismiss(new Alert()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Alert to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Alert);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): button.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$b = 'button';\n  const DATA_KEY$a = 'bs.button';\n  const EVENT_KEY$a = `.${DATA_KEY$a}`;\n  const DATA_API_KEY$7 = '.data-api';\n  const CLASS_NAME_ACTIVE$3 = 'active';\n  const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle=\"button\"]';\n  const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$7}`;\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Button extends BaseComponent {\n    // Getters\n    static get NAME() {\n      return NAME$b;\n    } // Public\n\n\n    toggle() {\n      // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n      this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Button.getOrCreateInstance(this);\n\n        if (config === 'toggle') {\n          data[config]();\n        }\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => {\n    event.preventDefault();\n    const button = event.target.closest(SELECTOR_DATA_TOGGLE$5);\n    const data = Button.getOrCreateInstance(button);\n    data.toggle();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Button to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Button);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): dom/manipulator.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  function normalizeData(val) {\n    if (val === 'true') {\n      return true;\n    }\n\n    if (val === 'false') {\n      return false;\n    }\n\n    if (val === Number(val).toString()) {\n      return Number(val);\n    }\n\n    if (val === '' || val === 'null') {\n      return null;\n    }\n\n    return val;\n  }\n\n  function normalizeDataKey(key) {\n    return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`);\n  }\n\n  const Manipulator = {\n    setDataAttribute(element, key, value) {\n      element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value);\n    },\n\n    removeDataAttribute(element, key) {\n      element.removeAttribute(`data-bs-${normalizeDataKey(key)}`);\n    },\n\n    getDataAttributes(element) {\n      if (!element) {\n        return {};\n      }\n\n      const attributes = {};\n      Object.keys(element.dataset).filter(key => key.startsWith('bs')).forEach(key => {\n        let pureKey = key.replace(/^bs/, '');\n        pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);\n        attributes[pureKey] = normalizeData(element.dataset[key]);\n      });\n      return attributes;\n    },\n\n    getDataAttribute(element, key) {\n      return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`));\n    },\n\n    offset(element) {\n      const rect = element.getBoundingClientRect();\n      return {\n        top: rect.top + document.body.scrollTop,\n        left: rect.left + document.body.scrollLeft\n      };\n    },\n\n    position(element) {\n      return {\n        top: element.offsetTop,\n        left: element.offsetLeft\n      };\n    }\n\n  };\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): carousel.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$a = 'carousel';\n  const DATA_KEY$9 = 'bs.carousel';\n  const EVENT_KEY$9 = `.${DATA_KEY$9}`;\n  const DATA_API_KEY$6 = '.data-api';\n  const ARROW_LEFT_KEY = 'ArrowLeft';\n  const ARROW_RIGHT_KEY = 'ArrowRight';\n  const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\n  const SWIPE_THRESHOLD = 40;\n  const Default$9 = {\n    interval: 5000,\n    keyboard: true,\n    slide: false,\n    pause: 'hover',\n    wrap: true,\n    touch: true\n  };\n  const DefaultType$9 = {\n    interval: '(number|boolean)',\n    keyboard: 'boolean',\n    slide: '(boolean|string)',\n    pause: '(string|boolean)',\n    wrap: 'boolean',\n    touch: 'boolean'\n  };\n  const ORDER_NEXT = 'next';\n  const ORDER_PREV = 'prev';\n  const DIRECTION_LEFT = 'left';\n  const DIRECTION_RIGHT = 'right';\n  const KEY_TO_DIRECTION = {\n    [ARROW_LEFT_KEY]: DIRECTION_RIGHT,\n    [ARROW_RIGHT_KEY]: DIRECTION_LEFT\n  };\n  const EVENT_SLIDE = `slide${EVENT_KEY$9}`;\n  const EVENT_SLID = `slid${EVENT_KEY$9}`;\n  const EVENT_KEYDOWN = `keydown${EVENT_KEY$9}`;\n  const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY$9}`;\n  const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY$9}`;\n  const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`;\n  const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`;\n  const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`;\n  const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`;\n  const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`;\n  const EVENT_DRAG_START = `dragstart${EVENT_KEY$9}`;\n  const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$9}${DATA_API_KEY$6}`;\n  const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$9}${DATA_API_KEY$6}`;\n  const CLASS_NAME_CAROUSEL = 'carousel';\n  const CLASS_NAME_ACTIVE$2 = 'active';\n  const CLASS_NAME_SLIDE = 'slide';\n  const CLASS_NAME_END = 'carousel-item-end';\n  const CLASS_NAME_START = 'carousel-item-start';\n  const CLASS_NAME_NEXT = 'carousel-item-next';\n  const CLASS_NAME_PREV = 'carousel-item-prev';\n  const CLASS_NAME_POINTER_EVENT = 'pointer-event';\n  const SELECTOR_ACTIVE$1 = '.active';\n  const SELECTOR_ACTIVE_ITEM = '.active.carousel-item';\n  const SELECTOR_ITEM = '.carousel-item';\n  const SELECTOR_ITEM_IMG = '.carousel-item img';\n  const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';\n  const SELECTOR_INDICATORS = '.carousel-indicators';\n  const SELECTOR_INDICATOR = '[data-bs-target]';\n  const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';\n  const SELECTOR_DATA_RIDE = '[data-bs-ride=\"carousel\"]';\n  const POINTER_TYPE_TOUCH = 'touch';\n  const POINTER_TYPE_PEN = 'pen';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Carousel extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._items = null;\n      this._interval = null;\n      this._activeElement = null;\n      this._isPaused = false;\n      this._isSliding = false;\n      this.touchTimeout = null;\n      this.touchStartX = 0;\n      this.touchDeltaX = 0;\n      this._config = this._getConfig(config);\n      this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element);\n      this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;\n      this._pointerEvent = Boolean(window.PointerEvent);\n\n      this._addEventListeners();\n    } // Getters\n\n\n    static get Default() {\n      return Default$9;\n    }\n\n    static get NAME() {\n      return NAME$a;\n    } // Public\n\n\n    next() {\n      this._slide(ORDER_NEXT);\n    }\n\n    nextWhenVisible() {\n      // Don't call next when the page isn't visible\n      // or the carousel or its parent isn't visible\n      if (!document.hidden && isVisible(this._element)) {\n        this.next();\n      }\n    }\n\n    prev() {\n      this._slide(ORDER_PREV);\n    }\n\n    pause(event) {\n      if (!event) {\n        this._isPaused = true;\n      }\n\n      if (SelectorEngine.findOne(SELECTOR_NEXT_PREV, this._element)) {\n        triggerTransitionEnd(this._element);\n        this.cycle(true);\n      }\n\n      clearInterval(this._interval);\n      this._interval = null;\n    }\n\n    cycle(event) {\n      if (!event) {\n        this._isPaused = false;\n      }\n\n      if (this._interval) {\n        clearInterval(this._interval);\n        this._interval = null;\n      }\n\n      if (this._config && this._config.interval && !this._isPaused) {\n        this._updateInterval();\n\n        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);\n      }\n    }\n\n    to(index) {\n      this._activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);\n\n      const activeIndex = this._getItemIndex(this._activeElement);\n\n      if (index > this._items.length - 1 || index < 0) {\n        return;\n      }\n\n      if (this._isSliding) {\n        EventHandler.one(this._element, EVENT_SLID, () => this.to(index));\n        return;\n      }\n\n      if (activeIndex === index) {\n        this.pause();\n        this.cycle();\n        return;\n      }\n\n      const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;\n\n      this._slide(order, this._items[index]);\n    } // Private\n\n\n    _getConfig(config) {\n      config = { ...Default$9,\n        ...Manipulator.getDataAttributes(this._element),\n        ...(typeof config === 'object' ? config : {})\n      };\n      typeCheckConfig(NAME$a, config, DefaultType$9);\n      return config;\n    }\n\n    _handleSwipe() {\n      const absDeltax = Math.abs(this.touchDeltaX);\n\n      if (absDeltax <= SWIPE_THRESHOLD) {\n        return;\n      }\n\n      const direction = absDeltax / this.touchDeltaX;\n      this.touchDeltaX = 0;\n\n      if (!direction) {\n        return;\n      }\n\n      this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT);\n    }\n\n    _addEventListeners() {\n      if (this._config.keyboard) {\n        EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event));\n      }\n\n      if (this._config.pause === 'hover') {\n        EventHandler.on(this._element, EVENT_MOUSEENTER, event => this.pause(event));\n        EventHandler.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event));\n      }\n\n      if (this._config.touch && this._touchSupported) {\n        this._addTouchEventListeners();\n      }\n    }\n\n    _addTouchEventListeners() {\n      const start = event => {\n        if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) {\n          this.touchStartX = event.clientX;\n        } else if (!this._pointerEvent) {\n          this.touchStartX = event.touches[0].clientX;\n        }\n      };\n\n      const move = event => {\n        // ensure swiping with one touch and not pinching\n        this.touchDeltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this.touchStartX;\n      };\n\n      const end = event => {\n        if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) {\n          this.touchDeltaX = event.clientX - this.touchStartX;\n        }\n\n        this._handleSwipe();\n\n        if (this._config.pause === 'hover') {\n          // If it's a touch-enabled device, mouseenter/leave are fired as\n          // part of the mouse compatibility events on first tap - the carousel\n          // would stop cycling until user tapped out of it;\n          // here, we listen for touchend, explicitly pause the carousel\n          // (as if it's the second time we tap on it, mouseenter compat event\n          // is NOT fired) and after a timeout (to allow for mouse compatibility\n          // events to fire) we explicitly restart cycling\n          this.pause();\n\n          if (this.touchTimeout) {\n            clearTimeout(this.touchTimeout);\n          }\n\n          this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval);\n        }\n      };\n\n      SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => {\n        EventHandler.on(itemImg, EVENT_DRAG_START, e => e.preventDefault());\n      });\n\n      if (this._pointerEvent) {\n        EventHandler.on(this._element, EVENT_POINTERDOWN, event => start(event));\n        EventHandler.on(this._element, EVENT_POINTERUP, event => end(event));\n\n        this._element.classList.add(CLASS_NAME_POINTER_EVENT);\n      } else {\n        EventHandler.on(this._element, EVENT_TOUCHSTART, event => start(event));\n        EventHandler.on(this._element, EVENT_TOUCHMOVE, event => move(event));\n        EventHandler.on(this._element, EVENT_TOUCHEND, event => end(event));\n      }\n    }\n\n    _keydown(event) {\n      if (/input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      const direction = KEY_TO_DIRECTION[event.key];\n\n      if (direction) {\n        event.preventDefault();\n\n        this._slide(direction);\n      }\n    }\n\n    _getItemIndex(element) {\n      this._items = element && element.parentNode ? SelectorEngine.find(SELECTOR_ITEM, element.parentNode) : [];\n      return this._items.indexOf(element);\n    }\n\n    _getItemByOrder(order, activeElement) {\n      const isNext = order === ORDER_NEXT;\n      return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);\n    }\n\n    _triggerSlideEvent(relatedTarget, eventDirectionName) {\n      const targetIndex = this._getItemIndex(relatedTarget);\n\n      const fromIndex = this._getItemIndex(SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element));\n\n      return EventHandler.trigger(this._element, EVENT_SLIDE, {\n        relatedTarget,\n        direction: eventDirectionName,\n        from: fromIndex,\n        to: targetIndex\n      });\n    }\n\n    _setActiveIndicatorElement(element) {\n      if (this._indicatorsElement) {\n        const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE$1, this._indicatorsElement);\n        activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2);\n        activeIndicator.removeAttribute('aria-current');\n        const indicators = SelectorEngine.find(SELECTOR_INDICATOR, this._indicatorsElement);\n\n        for (let i = 0; i < indicators.length; i++) {\n          if (Number.parseInt(indicators[i].getAttribute('data-bs-slide-to'), 10) === this._getItemIndex(element)) {\n            indicators[i].classList.add(CLASS_NAME_ACTIVE$2);\n            indicators[i].setAttribute('aria-current', 'true');\n            break;\n          }\n        }\n      }\n    }\n\n    _updateInterval() {\n      const element = this._activeElement || SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);\n\n      if (!element) {\n        return;\n      }\n\n      const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);\n\n      if (elementInterval) {\n        this._config.defaultInterval = this._config.defaultInterval || this._config.interval;\n        this._config.interval = elementInterval;\n      } else {\n        this._config.interval = this._config.defaultInterval || this._config.interval;\n      }\n    }\n\n    _slide(directionOrOrder, element) {\n      const order = this._directionToOrder(directionOrOrder);\n\n      const activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);\n\n      const activeElementIndex = this._getItemIndex(activeElement);\n\n      const nextElement = element || this._getItemByOrder(order, activeElement);\n\n      const nextElementIndex = this._getItemIndex(nextElement);\n\n      const isCycling = Boolean(this._interval);\n      const isNext = order === ORDER_NEXT;\n      const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;\n      const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;\n\n      const eventDirectionName = this._orderToDirection(order);\n\n      if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE$2)) {\n        this._isSliding = false;\n        return;\n      }\n\n      if (this._isSliding) {\n        return;\n      }\n\n      const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);\n\n      if (slideEvent.defaultPrevented) {\n        return;\n      }\n\n      if (!activeElement || !nextElement) {\n        // Some weirdness is happening, so we bail\n        return;\n      }\n\n      this._isSliding = true;\n\n      if (isCycling) {\n        this.pause();\n      }\n\n      this._setActiveIndicatorElement(nextElement);\n\n      this._activeElement = nextElement;\n\n      const triggerSlidEvent = () => {\n        EventHandler.trigger(this._element, EVENT_SLID, {\n          relatedTarget: nextElement,\n          direction: eventDirectionName,\n          from: activeElementIndex,\n          to: nextElementIndex\n        });\n      };\n\n      if (this._element.classList.contains(CLASS_NAME_SLIDE)) {\n        nextElement.classList.add(orderClassName);\n        reflow(nextElement);\n        activeElement.classList.add(directionalClassName);\n        nextElement.classList.add(directionalClassName);\n\n        const completeCallBack = () => {\n          nextElement.classList.remove(directionalClassName, orderClassName);\n          nextElement.classList.add(CLASS_NAME_ACTIVE$2);\n          activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName);\n          this._isSliding = false;\n          setTimeout(triggerSlidEvent, 0);\n        };\n\n        this._queueCallback(completeCallBack, activeElement, true);\n      } else {\n        activeElement.classList.remove(CLASS_NAME_ACTIVE$2);\n        nextElement.classList.add(CLASS_NAME_ACTIVE$2);\n        this._isSliding = false;\n        triggerSlidEvent();\n      }\n\n      if (isCycling) {\n        this.cycle();\n      }\n    }\n\n    _directionToOrder(direction) {\n      if (![DIRECTION_RIGHT, DIRECTION_LEFT].includes(direction)) {\n        return direction;\n      }\n\n      if (isRTL()) {\n        return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;\n      }\n\n      return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV;\n    }\n\n    _orderToDirection(order) {\n      if (![ORDER_NEXT, ORDER_PREV].includes(order)) {\n        return order;\n      }\n\n      if (isRTL()) {\n        return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;\n      }\n\n      return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;\n    } // Static\n\n\n    static carouselInterface(element, config) {\n      const data = Carousel.getOrCreateInstance(element, config);\n      let {\n        _config\n      } = data;\n\n      if (typeof config === 'object') {\n        _config = { ..._config,\n          ...config\n        };\n      }\n\n      const action = typeof config === 'string' ? config : _config.slide;\n\n      if (typeof config === 'number') {\n        data.to(config);\n      } else if (typeof action === 'string') {\n        if (typeof data[action] === 'undefined') {\n          throw new TypeError(`No method named \"${action}\"`);\n        }\n\n        data[action]();\n      } else if (_config.interval && _config.ride) {\n        data.pause();\n        data.cycle();\n      }\n    }\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        Carousel.carouselInterface(this, config);\n      });\n    }\n\n    static dataApiClickHandler(event) {\n      const target = getElementFromSelector(this);\n\n      if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {\n        return;\n      }\n\n      const config = { ...Manipulator.getDataAttributes(target),\n        ...Manipulator.getDataAttributes(this)\n      };\n      const slideIndex = this.getAttribute('data-bs-slide-to');\n\n      if (slideIndex) {\n        config.interval = false;\n      }\n\n      Carousel.carouselInterface(target, config);\n\n      if (slideIndex) {\n        Carousel.getInstance(target).to(slideIndex);\n      }\n\n      event.preventDefault();\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler);\n  EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => {\n    const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);\n\n    for (let i = 0, len = carousels.length; i < len; i++) {\n      Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Carousel to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Carousel);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): collapse.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$9 = 'collapse';\n  const DATA_KEY$8 = 'bs.collapse';\n  const EVENT_KEY$8 = `.${DATA_KEY$8}`;\n  const DATA_API_KEY$5 = '.data-api';\n  const Default$8 = {\n    toggle: true,\n    parent: ''\n  };\n  const DefaultType$8 = {\n    toggle: 'boolean',\n    parent: '(string|element)'\n  };\n  const EVENT_SHOW$5 = `show${EVENT_KEY$8}`;\n  const EVENT_SHOWN$5 = `shown${EVENT_KEY$8}`;\n  const EVENT_HIDE$5 = `hide${EVENT_KEY$8}`;\n  const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$8}`;\n  const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`;\n  const CLASS_NAME_SHOW$8 = 'show';\n  const CLASS_NAME_COLLAPSE = 'collapse';\n  const CLASS_NAME_COLLAPSING = 'collapsing';\n  const CLASS_NAME_COLLAPSED = 'collapsed';\n  const WIDTH = 'width';\n  const HEIGHT = 'height';\n  const SELECTOR_ACTIVES = '.show, .collapsing';\n  const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle=\"collapse\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Collapse extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._isTransitioning = false;\n      this._config = this._getConfig(config);\n      this._triggerArray = SelectorEngine.find(`${SELECTOR_DATA_TOGGLE$4}[href=\"#${this._element.id}\"],` + `${SELECTOR_DATA_TOGGLE$4}[data-bs-target=\"#${this._element.id}\"]`);\n      const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4);\n\n      for (let i = 0, len = toggleList.length; i < len; i++) {\n        const elem = toggleList[i];\n        const selector = getSelectorFromElement(elem);\n        const filterElement = SelectorEngine.find(selector).filter(foundElem => foundElem === this._element);\n\n        if (selector !== null && filterElement.length) {\n          this._selector = selector;\n\n          this._triggerArray.push(elem);\n        }\n      }\n\n      this._parent = this._config.parent ? this._getParent() : null;\n\n      if (!this._config.parent) {\n        this._addAriaAndCollapsedClass(this._element, this._triggerArray);\n      }\n\n      if (this._config.toggle) {\n        this.toggle();\n      }\n    } // Getters\n\n\n    static get Default() {\n      return Default$8;\n    }\n\n    static get NAME() {\n      return NAME$9;\n    } // Public\n\n\n    toggle() {\n      if (this._element.classList.contains(CLASS_NAME_SHOW$8)) {\n        this.hide();\n      } else {\n        this.show();\n      }\n    }\n\n    show() {\n      if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW$8)) {\n        return;\n      }\n\n      let actives;\n      let activesData;\n\n      if (this._parent) {\n        actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent).filter(elem => {\n          if (typeof this._config.parent === 'string') {\n            return elem.getAttribute('data-bs-parent') === this._config.parent;\n          }\n\n          return elem.classList.contains(CLASS_NAME_COLLAPSE);\n        });\n\n        if (actives.length === 0) {\n          actives = null;\n        }\n      }\n\n      const container = SelectorEngine.findOne(this._selector);\n\n      if (actives) {\n        const tempActiveData = actives.find(elem => container !== elem);\n        activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null;\n\n        if (activesData && activesData._isTransitioning) {\n          return;\n        }\n      }\n\n      const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$5);\n\n      if (startEvent.defaultPrevented) {\n        return;\n      }\n\n      if (actives) {\n        actives.forEach(elemActive => {\n          if (container !== elemActive) {\n            Collapse.collapseInterface(elemActive, 'hide');\n          }\n\n          if (!activesData) {\n            Data.set(elemActive, DATA_KEY$8, null);\n          }\n        });\n      }\n\n      const dimension = this._getDimension();\n\n      this._element.classList.remove(CLASS_NAME_COLLAPSE);\n\n      this._element.classList.add(CLASS_NAME_COLLAPSING);\n\n      this._element.style[dimension] = 0;\n\n      if (this._triggerArray.length) {\n        this._triggerArray.forEach(element => {\n          element.classList.remove(CLASS_NAME_COLLAPSED);\n          element.setAttribute('aria-expanded', true);\n        });\n      }\n\n      this.setTransitioning(true);\n\n      const complete = () => {\n        this._element.classList.remove(CLASS_NAME_COLLAPSING);\n\n        this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$8);\n\n        this._element.style[dimension] = '';\n        this.setTransitioning(false);\n        EventHandler.trigger(this._element, EVENT_SHOWN$5);\n      };\n\n      const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n      const scrollSize = `scroll${capitalizedDimension}`;\n\n      this._queueCallback(complete, this._element, true);\n\n      this._element.style[dimension] = `${this._element[scrollSize]}px`;\n    }\n\n    hide() {\n      if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW$8)) {\n        return;\n      }\n\n      const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$5);\n\n      if (startEvent.defaultPrevented) {\n        return;\n      }\n\n      const dimension = this._getDimension();\n\n      this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`;\n      reflow(this._element);\n\n      this._element.classList.add(CLASS_NAME_COLLAPSING);\n\n      this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$8);\n\n      const triggerArrayLength = this._triggerArray.length;\n\n      if (triggerArrayLength > 0) {\n        for (let i = 0; i < triggerArrayLength; i++) {\n          const trigger = this._triggerArray[i];\n          const elem = getElementFromSelector(trigger);\n\n          if (elem && !elem.classList.contains(CLASS_NAME_SHOW$8)) {\n            trigger.classList.add(CLASS_NAME_COLLAPSED);\n            trigger.setAttribute('aria-expanded', false);\n          }\n        }\n      }\n\n      this.setTransitioning(true);\n\n      const complete = () => {\n        this.setTransitioning(false);\n\n        this._element.classList.remove(CLASS_NAME_COLLAPSING);\n\n        this._element.classList.add(CLASS_NAME_COLLAPSE);\n\n        EventHandler.trigger(this._element, EVENT_HIDDEN$5);\n      };\n\n      this._element.style[dimension] = '';\n\n      this._queueCallback(complete, this._element, true);\n    }\n\n    setTransitioning(isTransitioning) {\n      this._isTransitioning = isTransitioning;\n    } // Private\n\n\n    _getConfig(config) {\n      config = { ...Default$8,\n        ...config\n      };\n      config.toggle = Boolean(config.toggle); // Coerce string values\n\n      typeCheckConfig(NAME$9, config, DefaultType$8);\n      return config;\n    }\n\n    _getDimension() {\n      return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT;\n    }\n\n    _getParent() {\n      let {\n        parent\n      } = this._config;\n      parent = getElement(parent);\n      const selector = `${SELECTOR_DATA_TOGGLE$4}[data-bs-parent=\"${parent}\"]`;\n      SelectorEngine.find(selector, parent).forEach(element => {\n        const selected = getElementFromSelector(element);\n\n        this._addAriaAndCollapsedClass(selected, [element]);\n      });\n      return parent;\n    }\n\n    _addAriaAndCollapsedClass(element, triggerArray) {\n      if (!element || !triggerArray.length) {\n        return;\n      }\n\n      const isOpen = element.classList.contains(CLASS_NAME_SHOW$8);\n      triggerArray.forEach(elem => {\n        if (isOpen) {\n          elem.classList.remove(CLASS_NAME_COLLAPSED);\n        } else {\n          elem.classList.add(CLASS_NAME_COLLAPSED);\n        }\n\n        elem.setAttribute('aria-expanded', isOpen);\n      });\n    } // Static\n\n\n    static collapseInterface(element, config) {\n      let data = Collapse.getInstance(element);\n      const _config = { ...Default$8,\n        ...Manipulator.getDataAttributes(element),\n        ...(typeof config === 'object' && config ? config : {})\n      };\n\n      if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {\n        _config.toggle = false;\n      }\n\n      if (!data) {\n        data = new Collapse(element, _config);\n      }\n\n      if (typeof config === 'string') {\n        if (typeof data[config] === 'undefined') {\n          throw new TypeError(`No method named \"${config}\"`);\n        }\n\n        data[config]();\n      }\n    }\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        Collapse.collapseInterface(this, config);\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) {\n    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n    if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') {\n      event.preventDefault();\n    }\n\n    const triggerData = Manipulator.getDataAttributes(this);\n    const selector = getSelectorFromElement(this);\n    const selectorElements = SelectorEngine.find(selector);\n    selectorElements.forEach(element => {\n      const data = Collapse.getInstance(element);\n      let config;\n\n      if (data) {\n        // update parent attribute\n        if (data._parent === null && typeof triggerData.parent === 'string') {\n          data._config.parent = triggerData.parent;\n          data._parent = data._getParent();\n        }\n\n        config = 'toggle';\n      } else {\n        config = triggerData;\n      }\n\n      Collapse.collapseInterface(element, config);\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Collapse to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Collapse);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): dropdown.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$8 = 'dropdown';\n  const DATA_KEY$7 = 'bs.dropdown';\n  const EVENT_KEY$7 = `.${DATA_KEY$7}`;\n  const DATA_API_KEY$4 = '.data-api';\n  const ESCAPE_KEY$2 = 'Escape';\n  const SPACE_KEY = 'Space';\n  const TAB_KEY = 'Tab';\n  const ARROW_UP_KEY = 'ArrowUp';\n  const ARROW_DOWN_KEY = 'ArrowDown';\n  const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button\n\n  const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEY}|${ARROW_DOWN_KEY}|${ESCAPE_KEY$2}`);\n  const EVENT_HIDE$4 = `hide${EVENT_KEY$7}`;\n  const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$7}`;\n  const EVENT_SHOW$4 = `show${EVENT_KEY$7}`;\n  const EVENT_SHOWN$4 = `shown${EVENT_KEY$7}`;\n  const EVENT_CLICK = `click${EVENT_KEY$7}`;\n  const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`;\n  const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$7}${DATA_API_KEY$4}`;\n  const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$7}${DATA_API_KEY$4}`;\n  const CLASS_NAME_SHOW$7 = 'show';\n  const CLASS_NAME_DROPUP = 'dropup';\n  const CLASS_NAME_DROPEND = 'dropend';\n  const CLASS_NAME_DROPSTART = 'dropstart';\n  const CLASS_NAME_NAVBAR = 'navbar';\n  const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle=\"dropdown\"]';\n  const SELECTOR_MENU = '.dropdown-menu';\n  const SELECTOR_NAVBAR_NAV = '.navbar-nav';\n  const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';\n  const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start';\n  const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end';\n  const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start';\n  const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end';\n  const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start';\n  const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start';\n  const Default$7 = {\n    offset: [0, 2],\n    boundary: 'clippingParents',\n    reference: 'toggle',\n    display: 'dynamic',\n    popperConfig: null,\n    autoClose: true\n  };\n  const DefaultType$7 = {\n    offset: '(array|string|function)',\n    boundary: '(string|element)',\n    reference: '(string|element|object)',\n    display: 'string',\n    popperConfig: '(null|object|function)',\n    autoClose: '(boolean|string)'\n  };\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Dropdown extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._popper = null;\n      this._config = this._getConfig(config);\n      this._menu = this._getMenuElement();\n      this._inNavbar = this._detectNavbar();\n\n      this._addEventListeners();\n    } // Getters\n\n\n    static get Default() {\n      return Default$7;\n    }\n\n    static get DefaultType() {\n      return DefaultType$7;\n    }\n\n    static get NAME() {\n      return NAME$8;\n    } // Public\n\n\n    toggle() {\n      if (isDisabled(this._element)) {\n        return;\n      }\n\n      const isActive = this._element.classList.contains(CLASS_NAME_SHOW$7);\n\n      if (isActive) {\n        this.hide();\n        return;\n      }\n\n      this.show();\n    }\n\n    show() {\n      if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW$7)) {\n        return;\n      }\n\n      const parent = Dropdown.getParentFromElement(this._element);\n      const relatedTarget = {\n        relatedTarget: this._element\n      };\n      const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, relatedTarget);\n\n      if (showEvent.defaultPrevented) {\n        return;\n      } // Totally disable Popper for Dropdowns in Navbar\n\n\n      if (this._inNavbar) {\n        Manipulator.setDataAttribute(this._menu, 'popper', 'none');\n      } else {\n        if (typeof Popper__namespace === 'undefined') {\n          throw new TypeError('Bootstrap\\'s dropdowns require Popper (https://popper.js.org)');\n        }\n\n        let referenceElement = this._element;\n\n        if (this._config.reference === 'parent') {\n          referenceElement = parent;\n        } else if (isElement(this._config.reference)) {\n          referenceElement = getElement(this._config.reference);\n        } else if (typeof this._config.reference === 'object') {\n          referenceElement = this._config.reference;\n        }\n\n        const popperConfig = this._getPopperConfig();\n\n        const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false);\n        this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);\n\n        if (isDisplayStatic) {\n          Manipulator.setDataAttribute(this._menu, 'popper', 'static');\n        }\n      } // If this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n\n      if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) {\n        [].concat(...document.body.children).forEach(elem => EventHandler.on(elem, 'mouseover', noop));\n      }\n\n      this._element.focus();\n\n      this._element.setAttribute('aria-expanded', true);\n\n      this._menu.classList.toggle(CLASS_NAME_SHOW$7);\n\n      this._element.classList.toggle(CLASS_NAME_SHOW$7);\n\n      EventHandler.trigger(this._element, EVENT_SHOWN$4, relatedTarget);\n    }\n\n    hide() {\n      if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW$7)) {\n        return;\n      }\n\n      const relatedTarget = {\n        relatedTarget: this._element\n      };\n\n      this._completeHide(relatedTarget);\n    }\n\n    dispose() {\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      super.dispose();\n    }\n\n    update() {\n      this._inNavbar = this._detectNavbar();\n\n      if (this._popper) {\n        this._popper.update();\n      }\n    } // Private\n\n\n    _addEventListeners() {\n      EventHandler.on(this._element, EVENT_CLICK, event => {\n        event.preventDefault();\n        this.toggle();\n      });\n    }\n\n    _completeHide(relatedTarget) {\n      const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4, relatedTarget);\n\n      if (hideEvent.defaultPrevented) {\n        return;\n      } // If this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n\n      if ('ontouchstart' in document.documentElement) {\n        [].concat(...document.body.children).forEach(elem => EventHandler.off(elem, 'mouseover', noop));\n      }\n\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      this._menu.classList.remove(CLASS_NAME_SHOW$7);\n\n      this._element.classList.remove(CLASS_NAME_SHOW$7);\n\n      this._element.setAttribute('aria-expanded', 'false');\n\n      Manipulator.removeDataAttribute(this._menu, 'popper');\n      EventHandler.trigger(this._element, EVENT_HIDDEN$4, relatedTarget);\n    }\n\n    _getConfig(config) {\n      config = { ...this.constructor.Default,\n        ...Manipulator.getDataAttributes(this._element),\n        ...config\n      };\n      typeCheckConfig(NAME$8, config, this.constructor.DefaultType);\n\n      if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {\n        // Popper virtual elements require a getBoundingClientRect method\n        throw new TypeError(`${NAME$8.toUpperCase()}: Option \"reference\" provided type \"object\" without a required \"getBoundingClientRect\" method.`);\n      }\n\n      return config;\n    }\n\n    _getMenuElement() {\n      return SelectorEngine.next(this._element, SELECTOR_MENU)[0];\n    }\n\n    _getPlacement() {\n      const parentDropdown = this._element.parentNode;\n\n      if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {\n        return PLACEMENT_RIGHT;\n      }\n\n      if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {\n        return PLACEMENT_LEFT;\n      } // We need to trim the value because custom properties can also include spaces\n\n\n      const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end';\n\n      if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {\n        return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP;\n      }\n\n      return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM;\n    }\n\n    _detectNavbar() {\n      return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null;\n    }\n\n    _getOffset() {\n      const {\n        offset\n      } = this._config;\n\n      if (typeof offset === 'string') {\n        return offset.split(',').map(val => Number.parseInt(val, 10));\n      }\n\n      if (typeof offset === 'function') {\n        return popperData => offset(popperData, this._element);\n      }\n\n      return offset;\n    }\n\n    _getPopperConfig() {\n      const defaultBsPopperConfig = {\n        placement: this._getPlacement(),\n        modifiers: [{\n          name: 'preventOverflow',\n          options: {\n            boundary: this._config.boundary\n          }\n        }, {\n          name: 'offset',\n          options: {\n            offset: this._getOffset()\n          }\n        }]\n      }; // Disable Popper if we have a static display\n\n      if (this._config.display === 'static') {\n        defaultBsPopperConfig.modifiers = [{\n          name: 'applyStyles',\n          enabled: false\n        }];\n      }\n\n      return { ...defaultBsPopperConfig,\n        ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)\n      };\n    }\n\n    _selectMenuItem({\n      key,\n      target\n    }) {\n      const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible);\n\n      if (!items.length) {\n        return;\n      } // if target isn't included in items (e.g. when expanding the dropdown)\n      // allow cycling to get the last item in case key equals ARROW_UP_KEY\n\n\n      getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();\n    } // Static\n\n\n    static dropdownInterface(element, config) {\n      const data = Dropdown.getOrCreateInstance(element, config);\n\n      if (typeof config === 'string') {\n        if (typeof data[config] === 'undefined') {\n          throw new TypeError(`No method named \"${config}\"`);\n        }\n\n        data[config]();\n      }\n    }\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        Dropdown.dropdownInterface(this, config);\n      });\n    }\n\n    static clearMenus(event) {\n      if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) {\n        return;\n      }\n\n      const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$3);\n\n      for (let i = 0, len = toggles.length; i < len; i++) {\n        const context = Dropdown.getInstance(toggles[i]);\n\n        if (!context || context._config.autoClose === false) {\n          continue;\n        }\n\n        if (!context._element.classList.contains(CLASS_NAME_SHOW$7)) {\n          continue;\n        }\n\n        const relatedTarget = {\n          relatedTarget: context._element\n        };\n\n        if (event) {\n          const composedPath = event.composedPath();\n          const isMenuTarget = composedPath.includes(context._menu);\n\n          if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {\n            continue;\n          } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu\n\n\n          if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY || /input|select|option|textarea|form/i.test(event.target.tagName))) {\n            continue;\n          }\n\n          if (event.type === 'click') {\n            relatedTarget.clickEvent = event;\n          }\n        }\n\n        context._completeHide(relatedTarget);\n      }\n    }\n\n    static getParentFromElement(element) {\n      return getElementFromSelector(element) || element.parentNode;\n    }\n\n    static dataApiKeydownHandler(event) {\n      // If not input/textarea:\n      //  - And not a key in REGEXP_KEYDOWN => not a dropdown command\n      // If input/textarea:\n      //  - If space key => not a dropdown command\n      //  - If key is other than escape\n      //    - If key is not up or down => not a dropdown command\n      //    - If trigger inside the menu => not a dropdown command\n      if (/input|textarea/i.test(event.target.tagName) ? event.key === SPACE_KEY || event.key !== ESCAPE_KEY$2 && (event.key !== ARROW_DOWN_KEY && event.key !== ARROW_UP_KEY || event.target.closest(SELECTOR_MENU)) : !REGEXP_KEYDOWN.test(event.key)) {\n        return;\n      }\n\n      const isActive = this.classList.contains(CLASS_NAME_SHOW$7);\n\n      if (!isActive && event.key === ESCAPE_KEY$2) {\n        return;\n      }\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (isDisabled(this)) {\n        return;\n      }\n\n      const getToggleButton = () => this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0];\n\n      if (event.key === ESCAPE_KEY$2) {\n        getToggleButton().focus();\n        Dropdown.clearMenus();\n        return;\n      }\n\n      if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {\n        if (!isActive) {\n          getToggleButton().click();\n        }\n\n        Dropdown.getInstance(getToggleButton())._selectMenuItem(event);\n\n        return;\n      }\n\n      if (!isActive || event.key === SPACE_KEY) {\n        Dropdown.clearMenus();\n      }\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);\n  EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);\n  EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus);\n  EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);\n  EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) {\n    event.preventDefault();\n    Dropdown.dropdownInterface(this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Dropdown to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Dropdown);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): util/scrollBar.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';\n  const SELECTOR_STICKY_CONTENT = '.sticky-top';\n\n  class ScrollBarHelper {\n    constructor() {\n      this._element = document.body;\n    }\n\n    getWidth() {\n      // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes\n      const documentWidth = document.documentElement.clientWidth;\n      return Math.abs(window.innerWidth - documentWidth);\n    }\n\n    hide() {\n      const width = this.getWidth();\n\n      this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width\n\n\n      this._setElementAttributes(this._element, 'paddingRight', calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth\n\n\n      this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width);\n\n      this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);\n    }\n\n    _disableOverFlow() {\n      this._saveInitialAttribute(this._element, 'overflow');\n\n      this._element.style.overflow = 'hidden';\n    }\n\n    _setElementAttributes(selector, styleProp, callback) {\n      const scrollbarWidth = this.getWidth();\n\n      const manipulationCallBack = element => {\n        if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {\n          return;\n        }\n\n        this._saveInitialAttribute(element, styleProp);\n\n        const calculatedValue = window.getComputedStyle(element)[styleProp];\n        element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;\n      };\n\n      this._applyManipulationCallback(selector, manipulationCallBack);\n    }\n\n    reset() {\n      this._resetElementAttributes(this._element, 'overflow');\n\n      this._resetElementAttributes(this._element, 'paddingRight');\n\n      this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');\n\n      this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');\n    }\n\n    _saveInitialAttribute(element, styleProp) {\n      const actualValue = element.style[styleProp];\n\n      if (actualValue) {\n        Manipulator.setDataAttribute(element, styleProp, actualValue);\n      }\n    }\n\n    _resetElementAttributes(selector, styleProp) {\n      const manipulationCallBack = element => {\n        const value = Manipulator.getDataAttribute(element, styleProp);\n\n        if (typeof value === 'undefined') {\n          element.style.removeProperty(styleProp);\n        } else {\n          Manipulator.removeDataAttribute(element, styleProp);\n          element.style[styleProp] = value;\n        }\n      };\n\n      this._applyManipulationCallback(selector, manipulationCallBack);\n    }\n\n    _applyManipulationCallback(selector, callBack) {\n      if (isElement(selector)) {\n        callBack(selector);\n      } else {\n        SelectorEngine.find(selector, this._element).forEach(callBack);\n      }\n    }\n\n    isOverflowing() {\n      return this.getWidth() > 0;\n    }\n\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): util/backdrop.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  const Default$6 = {\n    isVisible: true,\n    // if false, we use the backdrop helper without adding any element to the dom\n    isAnimated: false,\n    rootElement: 'body',\n    // give the choice to place backdrop under different elements\n    clickCallback: null\n  };\n  const DefaultType$6 = {\n    isVisible: 'boolean',\n    isAnimated: 'boolean',\n    rootElement: '(element|string)',\n    clickCallback: '(function|null)'\n  };\n  const NAME$7 = 'backdrop';\n  const CLASS_NAME_BACKDROP = 'modal-backdrop';\n  const CLASS_NAME_FADE$5 = 'fade';\n  const CLASS_NAME_SHOW$6 = 'show';\n  const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$7}`;\n\n  class Backdrop {\n    constructor(config) {\n      this._config = this._getConfig(config);\n      this._isAppended = false;\n      this._element = null;\n    }\n\n    show(callback) {\n      if (!this._config.isVisible) {\n        execute(callback);\n        return;\n      }\n\n      this._append();\n\n      if (this._config.isAnimated) {\n        reflow(this._getElement());\n      }\n\n      this._getElement().classList.add(CLASS_NAME_SHOW$6);\n\n      this._emulateAnimation(() => {\n        execute(callback);\n      });\n    }\n\n    hide(callback) {\n      if (!this._config.isVisible) {\n        execute(callback);\n        return;\n      }\n\n      this._getElement().classList.remove(CLASS_NAME_SHOW$6);\n\n      this._emulateAnimation(() => {\n        this.dispose();\n        execute(callback);\n      });\n    } // Private\n\n\n    _getElement() {\n      if (!this._element) {\n        const backdrop = document.createElement('div');\n        backdrop.className = CLASS_NAME_BACKDROP;\n\n        if (this._config.isAnimated) {\n          backdrop.classList.add(CLASS_NAME_FADE$5);\n        }\n\n        this._element = backdrop;\n      }\n\n      return this._element;\n    }\n\n    _getConfig(config) {\n      config = { ...Default$6,\n        ...(typeof config === 'object' ? config : {})\n      }; // use getElement() with the default \"body\" to get a fresh Element on each instantiation\n\n      config.rootElement = getElement(config.rootElement);\n      typeCheckConfig(NAME$7, config, DefaultType$6);\n      return config;\n    }\n\n    _append() {\n      if (this._isAppended) {\n        return;\n      }\n\n      this._config.rootElement.appendChild(this._getElement());\n\n      EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => {\n        execute(this._config.clickCallback);\n      });\n      this._isAppended = true;\n    }\n\n    dispose() {\n      if (!this._isAppended) {\n        return;\n      }\n\n      EventHandler.off(this._element, EVENT_MOUSEDOWN);\n\n      this._element.remove();\n\n      this._isAppended = false;\n    }\n\n    _emulateAnimation(callback) {\n      executeAfterTransition(callback, this._getElement(), this._config.isAnimated);\n    }\n\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): modal.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$6 = 'modal';\n  const DATA_KEY$6 = 'bs.modal';\n  const EVENT_KEY$6 = `.${DATA_KEY$6}`;\n  const DATA_API_KEY$3 = '.data-api';\n  const ESCAPE_KEY$1 = 'Escape';\n  const Default$5 = {\n    backdrop: true,\n    keyboard: true,\n    focus: true\n  };\n  const DefaultType$5 = {\n    backdrop: '(boolean|string)',\n    keyboard: 'boolean',\n    focus: 'boolean'\n  };\n  const EVENT_HIDE$3 = `hide${EVENT_KEY$6}`;\n  const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$6}`;\n  const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$6}`;\n  const EVENT_SHOW$3 = `show${EVENT_KEY$6}`;\n  const EVENT_SHOWN$3 = `shown${EVENT_KEY$6}`;\n  const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$6}`;\n  const EVENT_RESIZE = `resize${EVENT_KEY$6}`;\n  const EVENT_CLICK_DISMISS$2 = `click.dismiss${EVENT_KEY$6}`;\n  const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$6}`;\n  const EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY$6}`;\n  const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$6}`;\n  const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`;\n  const CLASS_NAME_OPEN = 'modal-open';\n  const CLASS_NAME_FADE$4 = 'fade';\n  const CLASS_NAME_SHOW$5 = 'show';\n  const CLASS_NAME_STATIC = 'modal-static';\n  const SELECTOR_DIALOG = '.modal-dialog';\n  const SELECTOR_MODAL_BODY = '.modal-body';\n  const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle=\"modal\"]';\n  const SELECTOR_DATA_DISMISS$2 = '[data-bs-dismiss=\"modal\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Modal extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._config = this._getConfig(config);\n      this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);\n      this._backdrop = this._initializeBackDrop();\n      this._isShown = false;\n      this._ignoreBackdropClick = false;\n      this._isTransitioning = false;\n      this._scrollBar = new ScrollBarHelper();\n    } // Getters\n\n\n    static get Default() {\n      return Default$5;\n    }\n\n    static get NAME() {\n      return NAME$6;\n    } // Public\n\n\n    toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    }\n\n    show(relatedTarget) {\n      if (this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, {\n        relatedTarget\n      });\n\n      if (showEvent.defaultPrevented) {\n        return;\n      }\n\n      this._isShown = true;\n\n      if (this._isAnimated()) {\n        this._isTransitioning = true;\n      }\n\n      this._scrollBar.hide();\n\n      document.body.classList.add(CLASS_NAME_OPEN);\n\n      this._adjustDialog();\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      EventHandler.on(this._element, EVENT_CLICK_DISMISS$2, SELECTOR_DATA_DISMISS$2, event => this.hide(event));\n      EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => {\n        EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, event => {\n          if (event.target === this._element) {\n            this._ignoreBackdropClick = true;\n          }\n        });\n      });\n\n      this._showBackdrop(() => this._showElement(relatedTarget));\n    }\n\n    hide(event) {\n      if (event && ['A', 'AREA'].includes(event.target.tagName)) {\n        event.preventDefault();\n      }\n\n      if (!this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3);\n\n      if (hideEvent.defaultPrevented) {\n        return;\n      }\n\n      this._isShown = false;\n\n      const isAnimated = this._isAnimated();\n\n      if (isAnimated) {\n        this._isTransitioning = true;\n      }\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      EventHandler.off(document, EVENT_FOCUSIN$2);\n\n      this._element.classList.remove(CLASS_NAME_SHOW$5);\n\n      EventHandler.off(this._element, EVENT_CLICK_DISMISS$2);\n      EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS);\n\n      this._queueCallback(() => this._hideModal(), this._element, isAnimated);\n    }\n\n    dispose() {\n      [window, this._dialog].forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY$6));\n\n      this._backdrop.dispose();\n\n      super.dispose();\n      /**\n       * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`\n       * Do not move `document` in `htmlElements` array\n       * It will remove `EVENT_CLICK_DATA_API` event that should remain\n       */\n\n      EventHandler.off(document, EVENT_FOCUSIN$2);\n    }\n\n    handleUpdate() {\n      this._adjustDialog();\n    } // Private\n\n\n    _initializeBackDrop() {\n      return new Backdrop({\n        isVisible: Boolean(this._config.backdrop),\n        // 'static' option will be translated to true, and booleans will keep their value\n        isAnimated: this._isAnimated()\n      });\n    }\n\n    _getConfig(config) {\n      config = { ...Default$5,\n        ...Manipulator.getDataAttributes(this._element),\n        ...(typeof config === 'object' ? config : {})\n      };\n      typeCheckConfig(NAME$6, config, DefaultType$5);\n      return config;\n    }\n\n    _showElement(relatedTarget) {\n      const isAnimated = this._isAnimated();\n\n      const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog);\n\n      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n        // Don't move modal's DOM position\n        document.body.appendChild(this._element);\n      }\n\n      this._element.style.display = 'block';\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.setAttribute('aria-modal', true);\n\n      this._element.setAttribute('role', 'dialog');\n\n      this._element.scrollTop = 0;\n\n      if (modalBody) {\n        modalBody.scrollTop = 0;\n      }\n\n      if (isAnimated) {\n        reflow(this._element);\n      }\n\n      this._element.classList.add(CLASS_NAME_SHOW$5);\n\n      if (this._config.focus) {\n        this._enforceFocus();\n      }\n\n      const transitionComplete = () => {\n        if (this._config.focus) {\n          this._element.focus();\n        }\n\n        this._isTransitioning = false;\n        EventHandler.trigger(this._element, EVENT_SHOWN$3, {\n          relatedTarget\n        });\n      };\n\n      this._queueCallback(transitionComplete, this._dialog, isAnimated);\n    }\n\n    _enforceFocus() {\n      EventHandler.off(document, EVENT_FOCUSIN$2); // guard against infinite focus loop\n\n      EventHandler.on(document, EVENT_FOCUSIN$2, event => {\n        if (document !== event.target && this._element !== event.target && !this._element.contains(event.target)) {\n          this._element.focus();\n        }\n      });\n    }\n\n    _setEscapeEvent() {\n      if (this._isShown) {\n        EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => {\n          if (this._config.keyboard && event.key === ESCAPE_KEY$1) {\n            event.preventDefault();\n            this.hide();\n          } else if (!this._config.keyboard && event.key === ESCAPE_KEY$1) {\n            this._triggerBackdropTransition();\n          }\n        });\n      } else {\n        EventHandler.off(this._element, EVENT_KEYDOWN_DISMISS$1);\n      }\n    }\n\n    _setResizeEvent() {\n      if (this._isShown) {\n        EventHandler.on(window, EVENT_RESIZE, () => this._adjustDialog());\n      } else {\n        EventHandler.off(window, EVENT_RESIZE);\n      }\n    }\n\n    _hideModal() {\n      this._element.style.display = 'none';\n\n      this._element.setAttribute('aria-hidden', true);\n\n      this._element.removeAttribute('aria-modal');\n\n      this._element.removeAttribute('role');\n\n      this._isTransitioning = false;\n\n      this._backdrop.hide(() => {\n        document.body.classList.remove(CLASS_NAME_OPEN);\n\n        this._resetAdjustments();\n\n        this._scrollBar.reset();\n\n        EventHandler.trigger(this._element, EVENT_HIDDEN$3);\n      });\n    }\n\n    _showBackdrop(callback) {\n      EventHandler.on(this._element, EVENT_CLICK_DISMISS$2, event => {\n        if (this._ignoreBackdropClick) {\n          this._ignoreBackdropClick = false;\n          return;\n        }\n\n        if (event.target !== event.currentTarget) {\n          return;\n        }\n\n        if (this._config.backdrop === true) {\n          this.hide();\n        } else if (this._config.backdrop === 'static') {\n          this._triggerBackdropTransition();\n        }\n      });\n\n      this._backdrop.show(callback);\n    }\n\n    _isAnimated() {\n      return this._element.classList.contains(CLASS_NAME_FADE$4);\n    }\n\n    _triggerBackdropTransition() {\n      const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);\n\n      if (hideEvent.defaultPrevented) {\n        return;\n      }\n\n      const {\n        classList,\n        scrollHeight,\n        style\n      } = this._element;\n      const isModalOverflowing = scrollHeight > document.documentElement.clientHeight; // return if the following background transition hasn't yet completed\n\n      if (!isModalOverflowing && style.overflowY === 'hidden' || classList.contains(CLASS_NAME_STATIC)) {\n        return;\n      }\n\n      if (!isModalOverflowing) {\n        style.overflowY = 'hidden';\n      }\n\n      classList.add(CLASS_NAME_STATIC);\n\n      this._queueCallback(() => {\n        classList.remove(CLASS_NAME_STATIC);\n\n        if (!isModalOverflowing) {\n          this._queueCallback(() => {\n            style.overflowY = '';\n          }, this._dialog);\n        }\n      }, this._dialog);\n\n      this._element.focus();\n    } // ----------------------------------------------------------------------\n    // the following methods are used to handle overflowing modals\n    // ----------------------------------------------------------------------\n\n\n    _adjustDialog() {\n      const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n      const scrollbarWidth = this._scrollBar.getWidth();\n\n      const isBodyOverflowing = scrollbarWidth > 0;\n\n      if (!isBodyOverflowing && isModalOverflowing && !isRTL() || isBodyOverflowing && !isModalOverflowing && isRTL()) {\n        this._element.style.paddingLeft = `${scrollbarWidth}px`;\n      }\n\n      if (isBodyOverflowing && !isModalOverflowing && !isRTL() || !isBodyOverflowing && isModalOverflowing && isRTL()) {\n        this._element.style.paddingRight = `${scrollbarWidth}px`;\n      }\n    }\n\n    _resetAdjustments() {\n      this._element.style.paddingLeft = '';\n      this._element.style.paddingRight = '';\n    } // Static\n\n\n    static jQueryInterface(config, relatedTarget) {\n      return this.each(function () {\n        const data = Modal.getOrCreateInstance(this, config);\n\n        if (typeof config !== 'string') {\n          return;\n        }\n\n        if (typeof data[config] === 'undefined') {\n          throw new TypeError(`No method named \"${config}\"`);\n        }\n\n        data[config](relatedTarget);\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) {\n    const target = getElementFromSelector(this);\n\n    if (['A', 'AREA'].includes(this.tagName)) {\n      event.preventDefault();\n    }\n\n    EventHandler.one(target, EVENT_SHOW$3, showEvent => {\n      if (showEvent.defaultPrevented) {\n        // only register focus restorer if modal will actually get shown\n        return;\n      }\n\n      EventHandler.one(target, EVENT_HIDDEN$3, () => {\n        if (isVisible(this)) {\n          this.focus();\n        }\n      });\n    });\n    const data = Modal.getOrCreateInstance(target);\n    data.toggle(this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Modal to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Modal);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): offcanvas.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$5 = 'offcanvas';\n  const DATA_KEY$5 = 'bs.offcanvas';\n  const EVENT_KEY$5 = `.${DATA_KEY$5}`;\n  const DATA_API_KEY$2 = '.data-api';\n  const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$5}${DATA_API_KEY$2}`;\n  const ESCAPE_KEY = 'Escape';\n  const Default$4 = {\n    backdrop: true,\n    keyboard: true,\n    scroll: false\n  };\n  const DefaultType$4 = {\n    backdrop: 'boolean',\n    keyboard: 'boolean',\n    scroll: 'boolean'\n  };\n  const CLASS_NAME_SHOW$4 = 'show';\n  const OPEN_SELECTOR = '.offcanvas.show';\n  const EVENT_SHOW$2 = `show${EVENT_KEY$5}`;\n  const EVENT_SHOWN$2 = `shown${EVENT_KEY$5}`;\n  const EVENT_HIDE$2 = `hide${EVENT_KEY$5}`;\n  const EVENT_HIDDEN$2 = `hidden${EVENT_KEY$5}`;\n  const EVENT_FOCUSIN$1 = `focusin${EVENT_KEY$5}`;\n  const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$5}${DATA_API_KEY$2}`;\n  const EVENT_CLICK_DISMISS$1 = `click.dismiss${EVENT_KEY$5}`;\n  const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$5}`;\n  const SELECTOR_DATA_DISMISS$1 = '[data-bs-dismiss=\"offcanvas\"]';\n  const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle=\"offcanvas\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Offcanvas extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._config = this._getConfig(config);\n      this._isShown = false;\n      this._backdrop = this._initializeBackDrop();\n\n      this._addEventListeners();\n    } // Getters\n\n\n    static get NAME() {\n      return NAME$5;\n    }\n\n    static get Default() {\n      return Default$4;\n    } // Public\n\n\n    toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    }\n\n    show(relatedTarget) {\n      if (this._isShown) {\n        return;\n      }\n\n      const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$2, {\n        relatedTarget\n      });\n\n      if (showEvent.defaultPrevented) {\n        return;\n      }\n\n      this._isShown = true;\n      this._element.style.visibility = 'visible';\n\n      this._backdrop.show();\n\n      if (!this._config.scroll) {\n        new ScrollBarHelper().hide();\n\n        this._enforceFocusOnElement(this._element);\n      }\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.setAttribute('aria-modal', true);\n\n      this._element.setAttribute('role', 'dialog');\n\n      this._element.classList.add(CLASS_NAME_SHOW$4);\n\n      const completeCallBack = () => {\n        EventHandler.trigger(this._element, EVENT_SHOWN$2, {\n          relatedTarget\n        });\n      };\n\n      this._queueCallback(completeCallBack, this._element, true);\n    }\n\n    hide() {\n      if (!this._isShown) {\n        return;\n      }\n\n      const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$2);\n\n      if (hideEvent.defaultPrevented) {\n        return;\n      }\n\n      EventHandler.off(document, EVENT_FOCUSIN$1);\n\n      this._element.blur();\n\n      this._isShown = false;\n\n      this._element.classList.remove(CLASS_NAME_SHOW$4);\n\n      this._backdrop.hide();\n\n      const completeCallback = () => {\n        this._element.setAttribute('aria-hidden', true);\n\n        this._element.removeAttribute('aria-modal');\n\n        this._element.removeAttribute('role');\n\n        this._element.style.visibility = 'hidden';\n\n        if (!this._config.scroll) {\n          new ScrollBarHelper().reset();\n        }\n\n        EventHandler.trigger(this._element, EVENT_HIDDEN$2);\n      };\n\n      this._queueCallback(completeCallback, this._element, true);\n    }\n\n    dispose() {\n      this._backdrop.dispose();\n\n      super.dispose();\n      EventHandler.off(document, EVENT_FOCUSIN$1);\n    } // Private\n\n\n    _getConfig(config) {\n      config = { ...Default$4,\n        ...Manipulator.getDataAttributes(this._element),\n        ...(typeof config === 'object' ? config : {})\n      };\n      typeCheckConfig(NAME$5, config, DefaultType$4);\n      return config;\n    }\n\n    _initializeBackDrop() {\n      return new Backdrop({\n        isVisible: this._config.backdrop,\n        isAnimated: true,\n        rootElement: this._element.parentNode,\n        clickCallback: () => this.hide()\n      });\n    }\n\n    _enforceFocusOnElement(element) {\n      EventHandler.off(document, EVENT_FOCUSIN$1); // guard against infinite focus loop\n\n      EventHandler.on(document, EVENT_FOCUSIN$1, event => {\n        if (document !== event.target && element !== event.target && !element.contains(event.target)) {\n          element.focus();\n        }\n      });\n      element.focus();\n    }\n\n    _addEventListeners() {\n      EventHandler.on(this._element, EVENT_CLICK_DISMISS$1, SELECTOR_DATA_DISMISS$1, () => this.hide());\n      EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {\n        if (this._config.keyboard && event.key === ESCAPE_KEY) {\n          this.hide();\n        }\n      });\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Offcanvas.getOrCreateInstance(this, config);\n\n        if (typeof config !== 'string') {\n          return;\n        }\n\n        if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n          throw new TypeError(`No method named \"${config}\"`);\n        }\n\n        data[config](this);\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) {\n    const target = getElementFromSelector(this);\n\n    if (['A', 'AREA'].includes(this.tagName)) {\n      event.preventDefault();\n    }\n\n    if (isDisabled(this)) {\n      return;\n    }\n\n    EventHandler.one(target, EVENT_HIDDEN$2, () => {\n      // focus on trigger when it is closed\n      if (isVisible(this)) {\n        this.focus();\n      }\n    }); // avoid conflict when clicking a toggler of an offcanvas, while another is open\n\n    const allReadyOpen = SelectorEngine.findOne(OPEN_SELECTOR);\n\n    if (allReadyOpen && allReadyOpen !== target) {\n      Offcanvas.getInstance(allReadyOpen).hide();\n    }\n\n    const data = Offcanvas.getOrCreateInstance(target);\n    data.toggle(this);\n  });\n  EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  defineJQueryPlugin(Offcanvas);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): util/sanitizer.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  const uriAttrs = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);\n  const ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i;\n  /**\n   * A pattern that recognizes a commonly useful subset of URLs that are safe.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i;\n  /**\n   * A pattern that matches safe data URLs. Only matches image, video and audio types.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  const DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[\\d+/a-z]+=*$/i;\n\n  const allowedAttribute = (attr, allowedAttributeList) => {\n    const attrName = attr.nodeName.toLowerCase();\n\n    if (allowedAttributeList.includes(attrName)) {\n      if (uriAttrs.has(attrName)) {\n        return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue));\n      }\n\n      return true;\n    }\n\n    const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp); // Check if a regular expression validates the attribute.\n\n    for (let i = 0, len = regExp.length; i < len; i++) {\n      if (regExp[i].test(attrName)) {\n        return true;\n      }\n    }\n\n    return false;\n  };\n\n  const DefaultAllowlist = {\n    // Global attributes allowed on any supplied element below.\n    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n    a: ['target', 'href', 'title', 'rel'],\n    area: [],\n    b: [],\n    br: [],\n    col: [],\n    code: [],\n    div: [],\n    em: [],\n    hr: [],\n    h1: [],\n    h2: [],\n    h3: [],\n    h4: [],\n    h5: [],\n    h6: [],\n    i: [],\n    img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n    li: [],\n    ol: [],\n    p: [],\n    pre: [],\n    s: [],\n    small: [],\n    span: [],\n    sub: [],\n    sup: [],\n    strong: [],\n    u: [],\n    ul: []\n  };\n  function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {\n    if (!unsafeHtml.length) {\n      return unsafeHtml;\n    }\n\n    if (sanitizeFn && typeof sanitizeFn === 'function') {\n      return sanitizeFn(unsafeHtml);\n    }\n\n    const domParser = new window.DOMParser();\n    const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');\n    const allowlistKeys = Object.keys(allowList);\n    const elements = [].concat(...createdDocument.body.querySelectorAll('*'));\n\n    for (let i = 0, len = elements.length; i < len; i++) {\n      const el = elements[i];\n      const elName = el.nodeName.toLowerCase();\n\n      if (!allowlistKeys.includes(elName)) {\n        el.remove();\n        continue;\n      }\n\n      const attributeList = [].concat(...el.attributes);\n      const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []);\n      attributeList.forEach(attr => {\n        if (!allowedAttribute(attr, allowedAttributes)) {\n          el.removeAttribute(attr.nodeName);\n        }\n      });\n    }\n\n    return createdDocument.body.innerHTML;\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): tooltip.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$4 = 'tooltip';\n  const DATA_KEY$4 = 'bs.tooltip';\n  const EVENT_KEY$4 = `.${DATA_KEY$4}`;\n  const CLASS_PREFIX$1 = 'bs-tooltip';\n  const BSCLS_PREFIX_REGEX$1 = new RegExp(`(^|\\\\s)${CLASS_PREFIX$1}\\\\S+`, 'g');\n  const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);\n  const DefaultType$3 = {\n    animation: 'boolean',\n    template: 'string',\n    title: '(string|element|function)',\n    trigger: 'string',\n    delay: '(number|object)',\n    html: 'boolean',\n    selector: '(string|boolean)',\n    placement: '(string|function)',\n    offset: '(array|string|function)',\n    container: '(string|element|boolean)',\n    fallbackPlacements: 'array',\n    boundary: '(string|element)',\n    customClass: '(string|function)',\n    sanitize: 'boolean',\n    sanitizeFn: '(null|function)',\n    allowList: 'object',\n    popperConfig: '(null|object|function)'\n  };\n  const AttachmentMap = {\n    AUTO: 'auto',\n    TOP: 'top',\n    RIGHT: isRTL() ? 'left' : 'right',\n    BOTTOM: 'bottom',\n    LEFT: isRTL() ? 'right' : 'left'\n  };\n  const Default$3 = {\n    animation: true,\n    template: '<div class=\"tooltip\" role=\"tooltip\">' + '<div class=\"tooltip-arrow\"></div>' + '<div class=\"tooltip-inner\"></div>' + '</div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    selector: false,\n    placement: 'top',\n    offset: [0, 0],\n    container: false,\n    fallbackPlacements: ['top', 'right', 'bottom', 'left'],\n    boundary: 'clippingParents',\n    customClass: '',\n    sanitize: true,\n    sanitizeFn: null,\n    allowList: DefaultAllowlist,\n    popperConfig: null\n  };\n  const Event$2 = {\n    HIDE: `hide${EVENT_KEY$4}`,\n    HIDDEN: `hidden${EVENT_KEY$4}`,\n    SHOW: `show${EVENT_KEY$4}`,\n    SHOWN: `shown${EVENT_KEY$4}`,\n    INSERTED: `inserted${EVENT_KEY$4}`,\n    CLICK: `click${EVENT_KEY$4}`,\n    FOCUSIN: `focusin${EVENT_KEY$4}`,\n    FOCUSOUT: `focusout${EVENT_KEY$4}`,\n    MOUSEENTER: `mouseenter${EVENT_KEY$4}`,\n    MOUSELEAVE: `mouseleave${EVENT_KEY$4}`\n  };\n  const CLASS_NAME_FADE$3 = 'fade';\n  const CLASS_NAME_MODAL = 'modal';\n  const CLASS_NAME_SHOW$3 = 'show';\n  const HOVER_STATE_SHOW = 'show';\n  const HOVER_STATE_OUT = 'out';\n  const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';\n  const TRIGGER_HOVER = 'hover';\n  const TRIGGER_FOCUS = 'focus';\n  const TRIGGER_CLICK = 'click';\n  const TRIGGER_MANUAL = 'manual';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Tooltip extends BaseComponent {\n    constructor(element, config) {\n      if (typeof Popper__namespace === 'undefined') {\n        throw new TypeError('Bootstrap\\'s tooltips require Popper (https://popper.js.org)');\n      }\n\n      super(element); // private\n\n      this._isEnabled = true;\n      this._timeout = 0;\n      this._hoverState = '';\n      this._activeTrigger = {};\n      this._popper = null; // Protected\n\n      this._config = this._getConfig(config);\n      this.tip = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    static get Default() {\n      return Default$3;\n    }\n\n    static get NAME() {\n      return NAME$4;\n    }\n\n    static get Event() {\n      return Event$2;\n    }\n\n    static get DefaultType() {\n      return DefaultType$3;\n    } // Public\n\n\n    enable() {\n      this._isEnabled = true;\n    }\n\n    disable() {\n      this._isEnabled = false;\n    }\n\n    toggleEnabled() {\n      this._isEnabled = !this._isEnabled;\n    }\n\n    toggle(event) {\n      if (!this._isEnabled) {\n        return;\n      }\n\n      if (event) {\n        const context = this._initializeOnDelegatedTarget(event);\n\n        context._activeTrigger.click = !context._activeTrigger.click;\n\n        if (context._isWithActiveTrigger()) {\n          context._enter(null, context);\n        } else {\n          context._leave(null, context);\n        }\n      } else {\n        if (this.getTipElement().classList.contains(CLASS_NAME_SHOW$3)) {\n          this._leave(null, this);\n\n          return;\n        }\n\n        this._enter(null, this);\n      }\n    }\n\n    dispose() {\n      clearTimeout(this._timeout);\n      EventHandler.off(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler);\n\n      if (this.tip) {\n        this.tip.remove();\n      }\n\n      if (this._popper) {\n        this._popper.destroy();\n      }\n\n      super.dispose();\n    }\n\n    show() {\n      if (this._element.style.display === 'none') {\n        throw new Error('Please use show on visible elements');\n      }\n\n      if (!(this.isWithContent() && this._isEnabled)) {\n        return;\n      }\n\n      const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW);\n      const shadowRoot = findShadowRoot(this._element);\n      const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element);\n\n      if (showEvent.defaultPrevented || !isInTheDom) {\n        return;\n      }\n\n      const tip = this.getTipElement();\n      const tipId = getUID(this.constructor.NAME);\n      tip.setAttribute('id', tipId);\n\n      this._element.setAttribute('aria-describedby', tipId);\n\n      this.setContent();\n\n      if (this._config.animation) {\n        tip.classList.add(CLASS_NAME_FADE$3);\n      }\n\n      const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;\n\n      const attachment = this._getAttachment(placement);\n\n      this._addAttachmentClass(attachment);\n\n      const {\n        container\n      } = this._config;\n      Data.set(tip, this.constructor.DATA_KEY, this);\n\n      if (!this._element.ownerDocument.documentElement.contains(this.tip)) {\n        container.appendChild(tip);\n        EventHandler.trigger(this._element, this.constructor.Event.INSERTED);\n      }\n\n      if (this._popper) {\n        this._popper.update();\n      } else {\n        this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));\n      }\n\n      tip.classList.add(CLASS_NAME_SHOW$3);\n      const customClass = typeof this._config.customClass === 'function' ? this._config.customClass() : this._config.customClass;\n\n      if (customClass) {\n        tip.classList.add(...customClass.split(' '));\n      } // If this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n\n      if ('ontouchstart' in document.documentElement) {\n        [].concat(...document.body.children).forEach(element => {\n          EventHandler.on(element, 'mouseover', noop);\n        });\n      }\n\n      const complete = () => {\n        const prevHoverState = this._hoverState;\n        this._hoverState = null;\n        EventHandler.trigger(this._element, this.constructor.Event.SHOWN);\n\n        if (prevHoverState === HOVER_STATE_OUT) {\n          this._leave(null, this);\n        }\n      };\n\n      const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE$3);\n\n      this._queueCallback(complete, this.tip, isAnimated);\n    }\n\n    hide() {\n      if (!this._popper) {\n        return;\n      }\n\n      const tip = this.getTipElement();\n\n      const complete = () => {\n        if (this._isWithActiveTrigger()) {\n          return;\n        }\n\n        if (this._hoverState !== HOVER_STATE_SHOW) {\n          tip.remove();\n        }\n\n        this._cleanTipClass();\n\n        this._element.removeAttribute('aria-describedby');\n\n        EventHandler.trigger(this._element, this.constructor.Event.HIDDEN);\n\n        if (this._popper) {\n          this._popper.destroy();\n\n          this._popper = null;\n        }\n      };\n\n      const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE);\n\n      if (hideEvent.defaultPrevented) {\n        return;\n      }\n\n      tip.classList.remove(CLASS_NAME_SHOW$3); // If this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n      if ('ontouchstart' in document.documentElement) {\n        [].concat(...document.body.children).forEach(element => EventHandler.off(element, 'mouseover', noop));\n      }\n\n      this._activeTrigger[TRIGGER_CLICK] = false;\n      this._activeTrigger[TRIGGER_FOCUS] = false;\n      this._activeTrigger[TRIGGER_HOVER] = false;\n      const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE$3);\n\n      this._queueCallback(complete, this.tip, isAnimated);\n\n      this._hoverState = '';\n    }\n\n    update() {\n      if (this._popper !== null) {\n        this._popper.update();\n      }\n    } // Protected\n\n\n    isWithContent() {\n      return Boolean(this.getTitle());\n    }\n\n    getTipElement() {\n      if (this.tip) {\n        return this.tip;\n      }\n\n      const element = document.createElement('div');\n      element.innerHTML = this._config.template;\n      this.tip = element.children[0];\n      return this.tip;\n    }\n\n    setContent() {\n      const tip = this.getTipElement();\n      this.setElementContent(SelectorEngine.findOne(SELECTOR_TOOLTIP_INNER, tip), this.getTitle());\n      tip.classList.remove(CLASS_NAME_FADE$3, CLASS_NAME_SHOW$3);\n    }\n\n    setElementContent(element, content) {\n      if (element === null) {\n        return;\n      }\n\n      if (isElement(content)) {\n        content = getElement(content); // content is a DOM node or a jQuery\n\n        if (this._config.html) {\n          if (content.parentNode !== element) {\n            element.innerHTML = '';\n            element.appendChild(content);\n          }\n        } else {\n          element.textContent = content.textContent;\n        }\n\n        return;\n      }\n\n      if (this._config.html) {\n        if (this._config.sanitize) {\n          content = sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn);\n        }\n\n        element.innerHTML = content;\n      } else {\n        element.textContent = content;\n      }\n    }\n\n    getTitle() {\n      let title = this._element.getAttribute('data-bs-original-title');\n\n      if (!title) {\n        title = typeof this._config.title === 'function' ? this._config.title.call(this._element) : this._config.title;\n      }\n\n      return title;\n    }\n\n    updateAttachment(attachment) {\n      if (attachment === 'right') {\n        return 'end';\n      }\n\n      if (attachment === 'left') {\n        return 'start';\n      }\n\n      return attachment;\n    } // Private\n\n\n    _initializeOnDelegatedTarget(event, context) {\n      const dataKey = this.constructor.DATA_KEY;\n      context = context || Data.get(event.delegateTarget, dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.delegateTarget, this._getDelegateConfig());\n        Data.set(event.delegateTarget, dataKey, context);\n      }\n\n      return context;\n    }\n\n    _getOffset() {\n      const {\n        offset\n      } = this._config;\n\n      if (typeof offset === 'string') {\n        return offset.split(',').map(val => Number.parseInt(val, 10));\n      }\n\n      if (typeof offset === 'function') {\n        return popperData => offset(popperData, this._element);\n      }\n\n      return offset;\n    }\n\n    _getPopperConfig(attachment) {\n      const defaultBsPopperConfig = {\n        placement: attachment,\n        modifiers: [{\n          name: 'flip',\n          options: {\n            fallbackPlacements: this._config.fallbackPlacements\n          }\n        }, {\n          name: 'offset',\n          options: {\n            offset: this._getOffset()\n          }\n        }, {\n          name: 'preventOverflow',\n          options: {\n            boundary: this._config.boundary\n          }\n        }, {\n          name: 'arrow',\n          options: {\n            element: `.${this.constructor.NAME}-arrow`\n          }\n        }, {\n          name: 'onChange',\n          enabled: true,\n          phase: 'afterWrite',\n          fn: data => this._handlePopperPlacementChange(data)\n        }],\n        onFirstUpdate: data => {\n          if (data.options.placement !== data.placement) {\n            this._handlePopperPlacementChange(data);\n          }\n        }\n      };\n      return { ...defaultBsPopperConfig,\n        ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)\n      };\n    }\n\n    _addAttachmentClass(attachment) {\n      this.getTipElement().classList.add(`${CLASS_PREFIX$1}-${this.updateAttachment(attachment)}`);\n    }\n\n    _getAttachment(placement) {\n      return AttachmentMap[placement.toUpperCase()];\n    }\n\n    _setListeners() {\n      const triggers = this._config.trigger.split(' ');\n\n      triggers.forEach(trigger => {\n        if (trigger === 'click') {\n          EventHandler.on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event));\n        } else if (trigger !== TRIGGER_MANUAL) {\n          const eventIn = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN;\n          const eventOut = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT;\n          EventHandler.on(this._element, eventIn, this._config.selector, event => this._enter(event));\n          EventHandler.on(this._element, eventOut, this._config.selector, event => this._leave(event));\n        }\n      });\n\n      this._hideModalHandler = () => {\n        if (this._element) {\n          this.hide();\n        }\n      };\n\n      EventHandler.on(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler);\n\n      if (this._config.selector) {\n        this._config = { ...this._config,\n          trigger: 'manual',\n          selector: ''\n        };\n      } else {\n        this._fixTitle();\n      }\n    }\n\n    _fixTitle() {\n      const title = this._element.getAttribute('title');\n\n      const originalTitleType = typeof this._element.getAttribute('data-bs-original-title');\n\n      if (title || originalTitleType !== 'string') {\n        this._element.setAttribute('data-bs-original-title', title || '');\n\n        if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {\n          this._element.setAttribute('aria-label', title);\n        }\n\n        this._element.setAttribute('title', '');\n      }\n    }\n\n    _enter(event, context) {\n      context = this._initializeOnDelegatedTarget(event, context);\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;\n      }\n\n      if (context.getTipElement().classList.contains(CLASS_NAME_SHOW$3) || context._hoverState === HOVER_STATE_SHOW) {\n        context._hoverState = HOVER_STATE_SHOW;\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HOVER_STATE_SHOW;\n\n      if (!context._config.delay || !context._config.delay.show) {\n        context.show();\n        return;\n      }\n\n      context._timeout = setTimeout(() => {\n        if (context._hoverState === HOVER_STATE_SHOW) {\n          context.show();\n        }\n      }, context._config.delay.show);\n    }\n\n    _leave(event, context) {\n      context = this._initializeOnDelegatedTarget(event, context);\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);\n      }\n\n      if (context._isWithActiveTrigger()) {\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HOVER_STATE_OUT;\n\n      if (!context._config.delay || !context._config.delay.hide) {\n        context.hide();\n        return;\n      }\n\n      context._timeout = setTimeout(() => {\n        if (context._hoverState === HOVER_STATE_OUT) {\n          context.hide();\n        }\n      }, context._config.delay.hide);\n    }\n\n    _isWithActiveTrigger() {\n      for (const trigger in this._activeTrigger) {\n        if (this._activeTrigger[trigger]) {\n          return true;\n        }\n      }\n\n      return false;\n    }\n\n    _getConfig(config) {\n      const dataAttributes = Manipulator.getDataAttributes(this._element);\n      Object.keys(dataAttributes).forEach(dataAttr => {\n        if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {\n          delete dataAttributes[dataAttr];\n        }\n      });\n      config = { ...this.constructor.Default,\n        ...dataAttributes,\n        ...(typeof config === 'object' && config ? config : {})\n      };\n      config.container = config.container === false ? document.body : getElement(config.container);\n\n      if (typeof config.delay === 'number') {\n        config.delay = {\n          show: config.delay,\n          hide: config.delay\n        };\n      }\n\n      if (typeof config.title === 'number') {\n        config.title = config.title.toString();\n      }\n\n      if (typeof config.content === 'number') {\n        config.content = config.content.toString();\n      }\n\n      typeCheckConfig(NAME$4, config, this.constructor.DefaultType);\n\n      if (config.sanitize) {\n        config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn);\n      }\n\n      return config;\n    }\n\n    _getDelegateConfig() {\n      const config = {};\n\n      if (this._config) {\n        for (const key in this._config) {\n          if (this.constructor.Default[key] !== this._config[key]) {\n            config[key] = this._config[key];\n          }\n        }\n      }\n\n      return config;\n    }\n\n    _cleanTipClass() {\n      const tip = this.getTipElement();\n      const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX$1);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass));\n      }\n    }\n\n    _handlePopperPlacementChange(popperData) {\n      const {\n        state\n      } = popperData;\n\n      if (!state) {\n        return;\n      }\n\n      this.tip = state.elements.popper;\n\n      this._cleanTipClass();\n\n      this._addAttachmentClass(this._getAttachment(state.placement));\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Tooltip.getOrCreateInstance(this, config);\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(`No method named \"${config}\"`);\n          }\n\n          data[config]();\n        }\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Tooltip to jQuery only if jQuery is present\n   */\n\n\n  defineJQueryPlugin(Tooltip);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): popover.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$3 = 'popover';\n  const DATA_KEY$3 = 'bs.popover';\n  const EVENT_KEY$3 = `.${DATA_KEY$3}`;\n  const CLASS_PREFIX = 'bs-popover';\n  const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g');\n  const Default$2 = { ...Tooltip.Default,\n    placement: 'right',\n    offset: [0, 8],\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\">' + '<div class=\"popover-arrow\"></div>' + '<h3 class=\"popover-header\"></h3>' + '<div class=\"popover-body\"></div>' + '</div>'\n  };\n  const DefaultType$2 = { ...Tooltip.DefaultType,\n    content: '(string|element|function)'\n  };\n  const Event$1 = {\n    HIDE: `hide${EVENT_KEY$3}`,\n    HIDDEN: `hidden${EVENT_KEY$3}`,\n    SHOW: `show${EVENT_KEY$3}`,\n    SHOWN: `shown${EVENT_KEY$3}`,\n    INSERTED: `inserted${EVENT_KEY$3}`,\n    CLICK: `click${EVENT_KEY$3}`,\n    FOCUSIN: `focusin${EVENT_KEY$3}`,\n    FOCUSOUT: `focusout${EVENT_KEY$3}`,\n    MOUSEENTER: `mouseenter${EVENT_KEY$3}`,\n    MOUSELEAVE: `mouseleave${EVENT_KEY$3}`\n  };\n  const CLASS_NAME_FADE$2 = 'fade';\n  const CLASS_NAME_SHOW$2 = 'show';\n  const SELECTOR_TITLE = '.popover-header';\n  const SELECTOR_CONTENT = '.popover-body';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Popover extends Tooltip {\n    // Getters\n    static get Default() {\n      return Default$2;\n    }\n\n    static get NAME() {\n      return NAME$3;\n    }\n\n    static get Event() {\n      return Event$1;\n    }\n\n    static get DefaultType() {\n      return DefaultType$2;\n    } // Overrides\n\n\n    isWithContent() {\n      return this.getTitle() || this._getContent();\n    }\n\n    getTipElement() {\n      if (this.tip) {\n        return this.tip;\n      }\n\n      this.tip = super.getTipElement();\n\n      if (!this.getTitle()) {\n        SelectorEngine.findOne(SELECTOR_TITLE, this.tip).remove();\n      }\n\n      if (!this._getContent()) {\n        SelectorEngine.findOne(SELECTOR_CONTENT, this.tip).remove();\n      }\n\n      return this.tip;\n    }\n\n    setContent() {\n      const tip = this.getTipElement(); // we use append for html objects to maintain js events\n\n      this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle());\n\n      let content = this._getContent();\n\n      if (typeof content === 'function') {\n        content = content.call(this._element);\n      }\n\n      this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content);\n      tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2);\n    } // Private\n\n\n    _addAttachmentClass(attachment) {\n      this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`);\n    }\n\n    _getContent() {\n      return this._element.getAttribute('data-bs-content') || this._config.content;\n    }\n\n    _cleanTipClass() {\n      const tip = this.getTipElement();\n      const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass));\n      }\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Popover.getOrCreateInstance(this, config);\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(`No method named \"${config}\"`);\n          }\n\n          data[config]();\n        }\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Popover to jQuery only if jQuery is present\n   */\n\n\n  defineJQueryPlugin(Popover);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): scrollspy.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$2 = 'scrollspy';\n  const DATA_KEY$2 = 'bs.scrollspy';\n  const EVENT_KEY$2 = `.${DATA_KEY$2}`;\n  const DATA_API_KEY$1 = '.data-api';\n  const Default$1 = {\n    offset: 10,\n    method: 'auto',\n    target: ''\n  };\n  const DefaultType$1 = {\n    offset: 'number',\n    method: 'string',\n    target: '(string|element)'\n  };\n  const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`;\n  const EVENT_SCROLL = `scroll${EVENT_KEY$2}`;\n  const EVENT_LOAD_DATA_API = `load${EVENT_KEY$2}${DATA_API_KEY$1}`;\n  const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';\n  const CLASS_NAME_ACTIVE$1 = 'active';\n  const SELECTOR_DATA_SPY = '[data-bs-spy=\"scroll\"]';\n  const SELECTOR_NAV_LIST_GROUP$1 = '.nav, .list-group';\n  const SELECTOR_NAV_LINKS = '.nav-link';\n  const SELECTOR_NAV_ITEMS = '.nav-item';\n  const SELECTOR_LIST_ITEMS = '.list-group-item';\n  const SELECTOR_DROPDOWN$1 = '.dropdown';\n  const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';\n  const METHOD_OFFSET = 'offset';\n  const METHOD_POSITION = 'position';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class ScrollSpy extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._scrollElement = this._element.tagName === 'BODY' ? window : this._element;\n      this._config = this._getConfig(config);\n      this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`;\n      this._offsets = [];\n      this._targets = [];\n      this._activeTarget = null;\n      this._scrollHeight = 0;\n      EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process());\n      this.refresh();\n\n      this._process();\n    } // Getters\n\n\n    static get Default() {\n      return Default$1;\n    }\n\n    static get NAME() {\n      return NAME$2;\n    } // Public\n\n\n    refresh() {\n      const autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;\n      const offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;\n      const offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;\n      this._offsets = [];\n      this._targets = [];\n      this._scrollHeight = this._getScrollHeight();\n      const targets = SelectorEngine.find(this._selector);\n      targets.map(element => {\n        const targetSelector = getSelectorFromElement(element);\n        const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null;\n\n        if (target) {\n          const targetBCR = target.getBoundingClientRect();\n\n          if (targetBCR.width || targetBCR.height) {\n            return [Manipulator[offsetMethod](target).top + offsetBase, targetSelector];\n          }\n        }\n\n        return null;\n      }).filter(item => item).sort((a, b) => a[0] - b[0]).forEach(item => {\n        this._offsets.push(item[0]);\n\n        this._targets.push(item[1]);\n      });\n    }\n\n    dispose() {\n      EventHandler.off(this._scrollElement, EVENT_KEY$2);\n      super.dispose();\n    } // Private\n\n\n    _getConfig(config) {\n      config = { ...Default$1,\n        ...Manipulator.getDataAttributes(this._element),\n        ...(typeof config === 'object' && config ? config : {})\n      };\n\n      if (typeof config.target !== 'string' && isElement(config.target)) {\n        let {\n          id\n        } = config.target;\n\n        if (!id) {\n          id = getUID(NAME$2);\n          config.target.id = id;\n        }\n\n        config.target = `#${id}`;\n      }\n\n      typeCheckConfig(NAME$2, config, DefaultType$1);\n      return config;\n    }\n\n    _getScrollTop() {\n      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;\n    }\n\n    _getScrollHeight() {\n      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n    }\n\n    _getOffsetHeight() {\n      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;\n    }\n\n    _process() {\n      const scrollTop = this._getScrollTop() + this._config.offset;\n\n      const scrollHeight = this._getScrollHeight();\n\n      const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();\n\n      if (this._scrollHeight !== scrollHeight) {\n        this.refresh();\n      }\n\n      if (scrollTop >= maxScroll) {\n        const target = this._targets[this._targets.length - 1];\n\n        if (this._activeTarget !== target) {\n          this._activate(target);\n        }\n\n        return;\n      }\n\n      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n        this._activeTarget = null;\n\n        this._clear();\n\n        return;\n      }\n\n      for (let i = this._offsets.length; i--;) {\n        const isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);\n\n        if (isActiveTarget) {\n          this._activate(this._targets[i]);\n        }\n      }\n    }\n\n    _activate(target) {\n      this._activeTarget = target;\n\n      this._clear();\n\n      const queries = this._selector.split(',').map(selector => `${selector}[data-bs-target=\"${target}\"],${selector}[href=\"${target}\"]`);\n\n      const link = SelectorEngine.findOne(queries.join(','));\n\n      if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {\n        SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, link.closest(SELECTOR_DROPDOWN$1)).classList.add(CLASS_NAME_ACTIVE$1);\n        link.classList.add(CLASS_NAME_ACTIVE$1);\n      } else {\n        // Set triggered link as active\n        link.classList.add(CLASS_NAME_ACTIVE$1);\n        SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP$1).forEach(listGroup => {\n          // Set triggered links parents as active\n          // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor\n          SelectorEngine.prev(listGroup, `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`).forEach(item => item.classList.add(CLASS_NAME_ACTIVE$1)); // Handle special case when .nav-link is inside .nav-item\n\n          SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS).forEach(navItem => {\n            SelectorEngine.children(navItem, SELECTOR_NAV_LINKS).forEach(item => item.classList.add(CLASS_NAME_ACTIVE$1));\n          });\n        });\n      }\n\n      EventHandler.trigger(this._scrollElement, EVENT_ACTIVATE, {\n        relatedTarget: target\n      });\n    }\n\n    _clear() {\n      SelectorEngine.find(this._selector).filter(node => node.classList.contains(CLASS_NAME_ACTIVE$1)).forEach(node => node.classList.remove(CLASS_NAME_ACTIVE$1));\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = ScrollSpy.getOrCreateInstance(this, config);\n\n        if (typeof config !== 'string') {\n          return;\n        }\n\n        if (typeof data[config] === 'undefined') {\n          throw new TypeError(`No method named \"${config}\"`);\n        }\n\n        data[config]();\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(window, EVENT_LOAD_DATA_API, () => {\n    SelectorEngine.find(SELECTOR_DATA_SPY).forEach(spy => new ScrollSpy(spy));\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .ScrollSpy to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(ScrollSpy);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): tab.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME$1 = 'tab';\n  const DATA_KEY$1 = 'bs.tab';\n  const EVENT_KEY$1 = `.${DATA_KEY$1}`;\n  const DATA_API_KEY = '.data-api';\n  const EVENT_HIDE$1 = `hide${EVENT_KEY$1}`;\n  const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$1}`;\n  const EVENT_SHOW$1 = `show${EVENT_KEY$1}`;\n  const EVENT_SHOWN$1 = `shown${EVENT_KEY$1}`;\n  const EVENT_CLICK_DATA_API = `click${EVENT_KEY$1}${DATA_API_KEY}`;\n  const CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu';\n  const CLASS_NAME_ACTIVE = 'active';\n  const CLASS_NAME_FADE$1 = 'fade';\n  const CLASS_NAME_SHOW$1 = 'show';\n  const SELECTOR_DROPDOWN = '.dropdown';\n  const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';\n  const SELECTOR_ACTIVE = '.active';\n  const SELECTOR_ACTIVE_UL = ':scope > li > .active';\n  const SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"tab\"], [data-bs-toggle=\"pill\"], [data-bs-toggle=\"list\"]';\n  const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';\n  const SELECTOR_DROPDOWN_ACTIVE_CHILD = ':scope > .dropdown-menu .active';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Tab extends BaseComponent {\n    // Getters\n    static get NAME() {\n      return NAME$1;\n    } // Public\n\n\n    show() {\n      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && this._element.classList.contains(CLASS_NAME_ACTIVE)) {\n        return;\n      }\n\n      let previous;\n      const target = getElementFromSelector(this._element);\n\n      const listElement = this._element.closest(SELECTOR_NAV_LIST_GROUP);\n\n      if (listElement) {\n        const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE;\n        previous = SelectorEngine.find(itemSelector, listElement);\n        previous = previous[previous.length - 1];\n      }\n\n      const hideEvent = previous ? EventHandler.trigger(previous, EVENT_HIDE$1, {\n        relatedTarget: this._element\n      }) : null;\n      const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$1, {\n        relatedTarget: previous\n      });\n\n      if (showEvent.defaultPrevented || hideEvent !== null && hideEvent.defaultPrevented) {\n        return;\n      }\n\n      this._activate(this._element, listElement);\n\n      const complete = () => {\n        EventHandler.trigger(previous, EVENT_HIDDEN$1, {\n          relatedTarget: this._element\n        });\n        EventHandler.trigger(this._element, EVENT_SHOWN$1, {\n          relatedTarget: previous\n        });\n      };\n\n      if (target) {\n        this._activate(target, target.parentNode, complete);\n      } else {\n        complete();\n      }\n    } // Private\n\n\n    _activate(element, container, callback) {\n      const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? SelectorEngine.find(SELECTOR_ACTIVE_UL, container) : SelectorEngine.children(container, SELECTOR_ACTIVE);\n      const active = activeElements[0];\n      const isTransitioning = callback && active && active.classList.contains(CLASS_NAME_FADE$1);\n\n      const complete = () => this._transitionComplete(element, active, callback);\n\n      if (active && isTransitioning) {\n        active.classList.remove(CLASS_NAME_SHOW$1);\n\n        this._queueCallback(complete, element, true);\n      } else {\n        complete();\n      }\n    }\n\n    _transitionComplete(element, active, callback) {\n      if (active) {\n        active.classList.remove(CLASS_NAME_ACTIVE);\n        const dropdownChild = SelectorEngine.findOne(SELECTOR_DROPDOWN_ACTIVE_CHILD, active.parentNode);\n\n        if (dropdownChild) {\n          dropdownChild.classList.remove(CLASS_NAME_ACTIVE);\n        }\n\n        if (active.getAttribute('role') === 'tab') {\n          active.setAttribute('aria-selected', false);\n        }\n      }\n\n      element.classList.add(CLASS_NAME_ACTIVE);\n\n      if (element.getAttribute('role') === 'tab') {\n        element.setAttribute('aria-selected', true);\n      }\n\n      reflow(element);\n\n      if (element.classList.contains(CLASS_NAME_FADE$1)) {\n        element.classList.add(CLASS_NAME_SHOW$1);\n      }\n\n      let parent = element.parentNode;\n\n      if (parent && parent.nodeName === 'LI') {\n        parent = parent.parentNode;\n      }\n\n      if (parent && parent.classList.contains(CLASS_NAME_DROPDOWN_MENU)) {\n        const dropdownElement = element.closest(SELECTOR_DROPDOWN);\n\n        if (dropdownElement) {\n          SelectorEngine.find(SELECTOR_DROPDOWN_TOGGLE, dropdownElement).forEach(dropdown => dropdown.classList.add(CLASS_NAME_ACTIVE));\n        }\n\n        element.setAttribute('aria-expanded', true);\n      }\n\n      if (callback) {\n        callback();\n      }\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Tab.getOrCreateInstance(this);\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(`No method named \"${config}\"`);\n          }\n\n          data[config]();\n        }\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n    if (['A', 'AREA'].includes(this.tagName)) {\n      event.preventDefault();\n    }\n\n    if (isDisabled(this)) {\n      return;\n    }\n\n    const data = Tab.getOrCreateInstance(this);\n    data.show();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Tab to jQuery only if jQuery is present\n   */\n\n  defineJQueryPlugin(Tab);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): toast.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  const NAME = 'toast';\n  const DATA_KEY = 'bs.toast';\n  const EVENT_KEY = `.${DATA_KEY}`;\n  const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;\n  const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;\n  const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;\n  const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;\n  const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`;\n  const EVENT_HIDE = `hide${EVENT_KEY}`;\n  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;\n  const EVENT_SHOW = `show${EVENT_KEY}`;\n  const EVENT_SHOWN = `shown${EVENT_KEY}`;\n  const CLASS_NAME_FADE = 'fade';\n  const CLASS_NAME_HIDE = 'hide';\n  const CLASS_NAME_SHOW = 'show';\n  const CLASS_NAME_SHOWING = 'showing';\n  const DefaultType = {\n    animation: 'boolean',\n    autohide: 'boolean',\n    delay: 'number'\n  };\n  const Default = {\n    animation: true,\n    autohide: true,\n    delay: 5000\n  };\n  const SELECTOR_DATA_DISMISS = '[data-bs-dismiss=\"toast\"]';\n  /**\n   * ------------------------------------------------------------------------\n   * Class Definition\n   * ------------------------------------------------------------------------\n   */\n\n  class Toast extends BaseComponent {\n    constructor(element, config) {\n      super(element);\n      this._config = this._getConfig(config);\n      this._timeout = null;\n      this._hasMouseInteraction = false;\n      this._hasKeyboardInteraction = false;\n\n      this._setListeners();\n    } // Getters\n\n\n    static get DefaultType() {\n      return DefaultType;\n    }\n\n    static get Default() {\n      return Default;\n    }\n\n    static get NAME() {\n      return NAME;\n    } // Public\n\n\n    show() {\n      const showEvent = EventHandler.trigger(this._element, EVENT_SHOW);\n\n      if (showEvent.defaultPrevented) {\n        return;\n      }\n\n      this._clearTimeout();\n\n      if (this._config.animation) {\n        this._element.classList.add(CLASS_NAME_FADE);\n      }\n\n      const complete = () => {\n        this._element.classList.remove(CLASS_NAME_SHOWING);\n\n        this._element.classList.add(CLASS_NAME_SHOW);\n\n        EventHandler.trigger(this._element, EVENT_SHOWN);\n\n        this._maybeScheduleHide();\n      };\n\n      this._element.classList.remove(CLASS_NAME_HIDE);\n\n      reflow(this._element);\n\n      this._element.classList.add(CLASS_NAME_SHOWING);\n\n      this._queueCallback(complete, this._element, this._config.animation);\n    }\n\n    hide() {\n      if (!this._element.classList.contains(CLASS_NAME_SHOW)) {\n        return;\n      }\n\n      const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE);\n\n      if (hideEvent.defaultPrevented) {\n        return;\n      }\n\n      const complete = () => {\n        this._element.classList.add(CLASS_NAME_HIDE);\n\n        EventHandler.trigger(this._element, EVENT_HIDDEN);\n      };\n\n      this._element.classList.remove(CLASS_NAME_SHOW);\n\n      this._queueCallback(complete, this._element, this._config.animation);\n    }\n\n    dispose() {\n      this._clearTimeout();\n\n      if (this._element.classList.contains(CLASS_NAME_SHOW)) {\n        this._element.classList.remove(CLASS_NAME_SHOW);\n      }\n\n      super.dispose();\n    } // Private\n\n\n    _getConfig(config) {\n      config = { ...Default,\n        ...Manipulator.getDataAttributes(this._element),\n        ...(typeof config === 'object' && config ? config : {})\n      };\n      typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    }\n\n    _maybeScheduleHide() {\n      if (!this._config.autohide) {\n        return;\n      }\n\n      if (this._hasMouseInteraction || this._hasKeyboardInteraction) {\n        return;\n      }\n\n      this._timeout = setTimeout(() => {\n        this.hide();\n      }, this._config.delay);\n    }\n\n    _onInteraction(event, isInteracting) {\n      switch (event.type) {\n        case 'mouseover':\n        case 'mouseout':\n          this._hasMouseInteraction = isInteracting;\n          break;\n\n        case 'focusin':\n        case 'focusout':\n          this._hasKeyboardInteraction = isInteracting;\n          break;\n      }\n\n      if (isInteracting) {\n        this._clearTimeout();\n\n        return;\n      }\n\n      const nextElement = event.relatedTarget;\n\n      if (this._element === nextElement || this._element.contains(nextElement)) {\n        return;\n      }\n\n      this._maybeScheduleHide();\n    }\n\n    _setListeners() {\n      EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());\n      EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true));\n      EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false));\n      EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true));\n      EventHandler.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false));\n    }\n\n    _clearTimeout() {\n      clearTimeout(this._timeout);\n      this._timeout = null;\n    } // Static\n\n\n    static jQueryInterface(config) {\n      return this.each(function () {\n        const data = Toast.getOrCreateInstance(this, config);\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(`No method named \"${config}\"`);\n          }\n\n          data[config](this);\n        }\n      });\n    }\n\n  }\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   * add .Toast to jQuery only if jQuery is present\n   */\n\n\n  defineJQueryPlugin(Toast);\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v5.0.2): index.umd.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  var index_umd = {\n    Alert,\n    Button,\n    Carousel,\n    Collapse,\n    Dropdown,\n    Modal,\n    Offcanvas,\n    Popover,\n    ScrollSpy,\n    Tab,\n    Toast,\n    Tooltip\n  };\n\n  return index_umd;\n\n})));\n//# sourceMappingURL=bootstrap.js.map\n"
  },
  {
    "path": "public/js/fatrat.js",
    "content": "(function($){\n\n    var option_id                       = $('#option_id').val();\n    var request_url                     = $('#request_url').val();\n    var success_redirect_url            = $('#success_redirect_url').val();\n    var collect_name                    = '胖鼠采集';\n    var collect_describe                = '';\n    var collect_type                    = 'list';\n    var collect_list_url                = '';\n    var collect_list_url_paging         = '';\n    var collect_list_range              = '';\n    var collect_list_rules              = '';\n    var collect_content_range           = '';\n    var collect_content_rules           = '';\n    var collect_rendering               = '1';\n    var collect_image_download          = '1';\n    var collect_image_path              = '1';\n    var collect_remove_head             = '1';\n    var collect_image_attribute         = 'src';\n    var collect_custom_content_head     = '';\n    var collect_custom_content_foot     = '';\n    var collect_keywords_replace_rule   = '';\n    var collect_play_timer              = {};\n\n    /**\n     * Spider Ajax\n     */\n    // 微信爬虫\n    $('.wx-spider-run-button').on('click', function(){\n        var collect_urls   = $('textarea[name=\"collect_wx_urls\"]').val();\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'custom_page',\n            collect_urls: collect_urls,\n            collect_name: 'wx',\n        }, '.spider-progress-bar', '.wx-spider-run-button');\n    });\n\n\n\n    //微信公众号历史采集\n    $('.wx-history-spider-run-button').on('click', function(){\n        if(!confirm(\"微信公众号历史爬取时间会久点, 请耐心等待...\")){\n            return;\n        }\n        let collect_wechat_app_name   = $('input[name=\"collect_wechat_app_name\"]').val();\n        let collect_wechat_app_start_number   = $('input[name=\"collect_wechat_app_start_number\"]').val();\n        let collect_wechat_app_number   = $('input[name=\"collect_wechat_app_number\"]').val();\n        let collect_wx_app_cookie   = $('textarea[name=\"collect_wx_app_cookie\"]').val();\n        let collect_wx_app_token   = $('input[name=\"collect_wx_app_token\"]').val();\n        ajax_collect_request_tool(request_url, {\n            action_func: 'wechat_history',\n            collect_wechat_app_name:collect_wechat_app_name,\n            collect_wechat_app_start_number:collect_wechat_app_start_number,\n            collect_wechat_app_number:collect_wechat_app_number,\n            collect_wx_app_cookie:collect_wx_app_cookie,\n            collect_wx_app_token:collect_wx_app_token\n        }, '.spider-progress-bar', '.wx-history-spider-run-button');\n    });\n\n    // 简书爬虫\n    $('.js-spider-run-button').on('click', function(){\n        var collect_urls   = $('textarea[name=\"collect_js_urls\"]').val();\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'custom_page',\n            collect_urls: collect_urls,\n            collect_name: 'js',\n        }, '.spider-progress-bar', '.js-spider-run-button');\n    });\n\n    // 知乎问答\n    $('.zh-spider-run-button').on('click', function(){\n        var collect_urls   = $('textarea[name=\"collect_zh_urls\"]').val();\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'custom_page',\n            collect_urls: collect_urls,\n            collect_name: 'zh',\n        }, '.spider-progress-bar', '.zh-spider-run-button');\n    });\n\n    $('.list-spider-run-button').on('click', function(){\n        if(!confirm(\"列表爬取时间会久点, 请耐心等待...\")){\n            return;\n        }\n\n        var option_id = $(this).attr('data-id');\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'list_page',\n            option_id: option_id,\n        }, '.spider-progress-bar', '.list-spider-run-button');\n    });\n\n    $('.history-page-spider-run-button').on('click', function(){\n        if(!confirm(\"请核实输入信息.\")){\n            return;\n        }\n\n        var collect_history_page_number   = $('input[name=\"collect_history_page_number\"]').val();\n        var collect_history_relus_id      = $('select[name=\"collect_history_relus\"]').val();\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'history_page',\n            collect_history_page_number: collect_history_page_number,\n            collect_history_relus_id: collect_history_relus_id,\n        }, '.spider-progress-bar', '.history-page-spider-run-button');\n\n    });\n\n    $('.details-spider-run-button').on('click', function(){\n        if(!confirm(\"请确认..\")){\n            return;\n        }\n\n        var collect_details_urls   = $('textarea[name=\"collect_details_urls\"]').val();\n        var collect_details_relus  = $('select[name=\"collect_details_relus\"]').val();\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'details_page',\n            collect_details_urls: collect_details_urls,\n            collect_details_relus: collect_details_relus,\n        }, '.spider-progress-bar', '.details-spider-run-button');\n    });\n\n    $('.all-spider-run-button').on('click', function(){\n        if(!confirm(\"采集马上开始, 请耐心等待...\")){\n            return;\n        }\n\n        var option_id = $(this).attr('data-id');\n        ajax_collect_request_tool(request_url, {\n            action_func: 'all_page',\n            option_id: option_id,\n        }, '.spider-progress-bar', '.all-spider-run-button');\n    });\n\n    // debug 功能\n    $('#debug-option').on('click', function(){\n        var debug_rule = new Array();\n        debug_rule['a'] = $('input[name=\"collect_debug_rule_a\"]').val() != \"\" ? $('input[name=\"collect_debug_rule_a\"]').val() : null ;\n        debug_rule['b'] = $('input[name=\"collect_debug_rule_b\"]').val() != \"\" ? $('input[name=\"collect_debug_rule_b\"]').val() : null ;\n        debug_rule['c'] = $('input[name=\"collect_debug_rule_c\"]').val() != \"\" ? $('input[name=\"collect_debug_rule_c\"]').val() : null ;\n        debug_rule['d'] = $('input[name=\"collect_debug_rule_d\"]').val() != \"\" ? $('input[name=\"collect_debug_rule_d\"]').val() : null ;\n\n        var debug_url      = $('input[name=\"debug_url\"]').val();\n        var debug_remove_head = $('input[name=\"debug_remove_head\"]:checked').val();\n        var debug_rendering = $('input[name=\"debug_rendering\"]:checked').val();\n        var debug_range    = $('input[name=\"debug_range\"]').val();\n        var debug_rules    = debug_rule['a']+'%'+debug_rule['b']+'|'+debug_rule['c']+'|'+debug_rule['d'];\n\n        ajax_collect_request_tool(request_url, {\n            action_func: 'debug',\n            debug_url: debug_url,\n            debug_remove_head: debug_remove_head,\n            debug_rendering: debug_rendering,\n            debug_range: debug_range,\n            debug_rules: debug_rules,\n        }, '', '#debug-option');\n\n    });\n\n\n    /**\n     * Option Ajax\n     */\n    $('#save-option-button').on('click', function(){\n        if(!confirm(\"请确认输入的配置.\")){\n            return;\n        }\n\n        var tmp_link = new Array();\n        var tmp_title = new Array();\n        var tmp_content = new Array();\n        var tmp_paging = new Array();\n\n        tmp_link['a'] = $('input[name=\"collect_list_rule_link_a\"]').val() != \"\" ? $('input[name=\"collect_list_rule_link_a\"]').val() : null ;\n        tmp_link['b'] = $('input[name=\"collect_list_rule_link_b\"]').val() != \"\" ? $('input[name=\"collect_list_rule_link_b\"]').val() : null ;\n        tmp_link['c'] = $('input[name=\"collect_list_rule_link_c\"]').val() != \"\" ? $('input[name=\"collect_list_rule_link_c\"]').val() : null ;\n        tmp_link['d'] = $('input[name=\"collect_list_rule_link_d\"]').val() != \"\" ? $('input[name=\"collect_list_rule_link_d\"]').val() : null ;\n        tmp_title['a'] = $('input[name=\"collect_content_rule_title_a\"]').val() != \"\" ? $('input[name=\"collect_content_rule_title_a\"]').val() : null ;\n        tmp_title['b'] = $('input[name=\"collect_content_rule_title_b\"]').val() != \"\" ? $('input[name=\"collect_content_rule_title_b\"]').val() : null ;\n        tmp_title['c'] = $('input[name=\"collect_content_rule_title_c\"]').val() != \"\" ? $('input[name=\"collect_content_rule_title_c\"]').val() : null ;\n        tmp_title['d'] = $('input[name=\"collect_content_rule_title_d\"]').val() != \"\" ? $('input[name=\"collect_content_rule_title_d\"]').val() : null ;\n        tmp_content['a'] = $('input[name=\"collect_content_rule_content_a\"]').val() != \"\" ? $('input[name=\"collect_content_rule_content_a\"]').val() : null ;\n        tmp_content['b'] = $('input[name=\"collect_content_rule_content_b\"]').val() != \"\" ? $('input[name=\"collect_content_rule_content_b\"]').val() : null ;\n        tmp_content['c'] = $('input[name=\"collect_content_rule_content_c\"]').val() != \"\" ? $('input[name=\"collect_content_rule_content_c\"]').val() : null ;\n        tmp_content['d'] = $('input[name=\"collect_content_rule_content_d\"]').val() != \"\" ? $('input[name=\"collect_content_rule_content_d\"]').val() : null ;\n        tmp_paging['a'] = $('input[name=\"collect_content_rule_paging_a\"]').val() != \"\" ? $('input[name=\"collect_content_rule_paging_a\"]').val() : null ;\n        tmp_paging['b'] = $('input[name=\"collect_content_rule_paging_b\"]').val() != \"\" ? $('input[name=\"collect_content_rule_paging_b\"]').val() : null ;\n        tmp_paging['c'] = $('input[name=\"collect_content_rule_paging_c\"]').val() != \"\" ? $('input[name=\"collect_content_rule_paging_c\"]').val() : null ;\n        tmp_paging['d'] = $('input[name=\"collect_content_rule_paging_d\"]').val() != \"\" ? $('input[name=\"collect_content_rule_paging_d\"]').val() : null ;\n\n        var options = {\n            action_func: 'save_option',\n            option_id: option_id,\n            collect_name: $('input[name=\"collect_name\"]').val(),\n            collect_describe: $('input[name=\"collect_describe\"]').val(),\n            collect_type: $('input[name=\"collect_type\"]:checked').val(),\n            collect_rendering: $('input[name=\"collect_rendering\"]:checked').val(),\n            collect_image_path: $('input[name=\"collect_image_path\"]:checked').val(),\n            collect_image_download: $('input[name=\"collect_image_download\"]:checked').val(),\n            collect_remove_head: $('input[name=\"collect_remove_head\"]:checked').val(),\n            collect_list_url: $('input[name=\"collect_list_url\"]').val(),\n            collect_list_url_paging: $('input[name=\"collect_list_url_paging\"]').val(),\n            collect_list_range: $('input[name=\"collect_list_range\"]').val(),\n            collect_list_rules: tmp_link['a'] + '%' + tmp_link['b'] + '|' + tmp_link['c'] + '|' + tmp_link['d'],\n            collect_content_range: $('input[name=\"collect_content_range\"]').val(),\n            collect_content_rules: tmp_title['a'] + '%' + tmp_title['b'] + '|' + tmp_title['c'] + '|' + tmp_title['d'] + ')(' + tmp_content['a'] + '%' + tmp_content['b'] + '|' + tmp_content['c'] + '|' + tmp_content['d'] + ')(' + tmp_paging['a'] + '%' + tmp_paging['b'] + '|' + tmp_paging['c'] + '|' + tmp_paging['d'],\n            collect_cookie: $('textarea[name=\"collect_cookie\"]').val(),\n            collect_image_attribute: $('input[name=\"collect_image_attribute\"]').val(),\n            collect_custom_content_head: $('textarea[name=\"collect_custom_content_head\"]').val(),\n            collect_custom_content_foot: $('textarea[name=\"collect_custom_content_foot\"]').val(),\n            collect_keywords_replace_rule: $('textarea[name=\"collect_keywords_replace_rule\"]').val(),\n            collect_keywords: $('textarea[name=\"collect_keywords\"]').val(),\n        }\n        ajax_option_request_tool(request_url, options, success_redirect_url);\n    });\n\n    $('.delete-option-button').on('click', function(){\n        // if(!confirm(\"请确认要删除这个规则吗?, 删除后此规则已采集的数据会转移到公共空间.\")){\n        if(!confirm(\"请确认要删除这个规则吗?\")){\n            return;\n        }\n\n        option_id = $(this).attr('data-value');\n\n        ajax_option_request_tool(request_url, {\n            action_func: 'del_option',\n            option_id: option_id,\n        }, success_redirect_url);\n    });\n\n    $('.import_default_configuration').on('click', function(){\n        if(!confirm(\"鼠友你好, 欢迎你使用一键导入采集规则功能, 它可以让你即刻体验采集的快感, 也可以帮你测试软件是否异常，导入例子后运行默认例子，例子无法采集数据说明插件的使用环境有问题哦。\")){\n            return;\n        }\n        if(!confirm(\"导入完成后, 要多多学习, 达到快速熟练使用胖鼠的目的. 胖鼠采集唯一官网 https://fatrat.cn\")){\n            return;\n        }\n        if(!confirm(\"添加规则时记得使用debugging功能.\")){\n            return;\n        }\n\n        ajax_option_request_tool(request_url, {\n            action_func: 'import_default_configuration',\n        }, success_redirect_url);\n    });\n\n    $('#save-release-option').on('click', function () {\n\n        var option_id   = $('#current_option_id').val();\n        var post_category = [];\n        var post_user = [];\n        var release_type = $('.release_type option:selected').val();\n        var extension_field = $('input[name=\"'+release_type+'_extension_field\"]:checked').val();\n\n        $(\".checkbox_post_category\").find(\"input[type='checkbox']:checked\").each(function (index, item) {\n            post_category.push($(this).val());\n        });\n\n        $(\".checkbox_post_user\").find(\"input[type='checkbox']:checked\").each(function (index, item) {\n            post_user.push($(this).val());\n        });\n        var post_status = $('input[name=\"post_status\"]:checked').val();\n        var post_thumbnail = $('input[name=\"post_thumbnail\"]:checked').val();\n\n        ajax_option_request_tool(request_url, {\n            action_func: 'save_option_release',\n            option_id: option_id,\n            release_category: post_category,\n            release_user: post_user,\n            release_status: post_status,\n            release_type: release_type,\n            extension_field: extension_field,\n            release_thumbnail: post_thumbnail,\n        }, success_redirect_url);\n    });\n\n    $('.frc_cron_button').on('click', function(){\n        if(!confirm(\"请确认您的选择?\")){\n            return;\n        }\n\n        var frc_option = $(this).attr('data-value');\n        var frc_value = $('input[name=\"'+frc_option+'\"]:checked').val();\n\n        ajax_option_request_tool(request_url, {\n            action_func: 'update_auto_config',\n            option: frc_option,\n            value: frc_value,\n        });\n    });\n\n    /**\n     * Import Ajax\n     */\n    // import article\n    $('#import-articles-button').on('click', function(){\n        if(!confirm(\"确认一下..\")){\n            return;\n        }\n        var collect_count = $('input[name=\"import-articles-count-button\"]').val();\n\n        ajax_import_data_request_tool(request_url, {\n            action_func: 'import_article',\n            collect_count: collect_count,\n        });\n    });\n\n    $('#import-articles-button_group').on('click', function(){\n        if(!confirm(\"确认一下..\")){\n            return;\n        }\n\n        ajax_import_data_request_tool(request_url, {\n            action_func: 'import_group_article',\n        });\n    });\n\n    $('.publish-article').on('click', function(){\n        if(!confirm(\"请确认发布信息, 马上为您发布. \")){\n            return;\n        }\n\n        var release_id   = $(this).attr('data-value');\n        var post_category = [];\n        var post_user = [];\n\n        $(\".checkbox_post_category\").find(\"input[type='checkbox']:checked\").each(function (index, item) {\n            post_category.push($(this).val());\n        });\n\n        $(\".checkbox_post_user\").find(\"input[type='checkbox']:checked\").each(function (index, item) {\n            post_user.push($(this).val());\n        });\n        var post_status = $('input[name=\"post_status\"]:checked').val();\n        var post_thumbnail = $('input[name=\"post_thumbnail\"]:checked').val();\n\n        ajax_import_data_request_tool(request_url, {\n            action_func: 'publish_article',\n            release_id: release_id,\n            post_category: post_category,\n            post_user: post_user,\n            post_status: post_status,\n            post_thumbnail: post_thumbnail,\n        }, success_redirect_url);\n    });\n\n    $('.preview-article').on('click', function(){\n        if(!confirm(\"预览功能, 文章会发布到文章列表里. 文章状态为: 草稿\")){\n            return;\n        }\n\n        var release_id   = $(this).attr('data-value');\n        var post_category = [];\n        $(\"input[type='checkbox']:checked\").each(function (index, item) {\n            post_category.push($(this).val());\n        });\n        var post_user = $('select[name=\"post_user\"]').val();\n        var post_status = $('input[name=\"post_status\"]:checked').val();\n\n        ajax_import_data_request_tool(request_url, {\n            action_func: 'preview_article',\n            release_id: release_id,\n            post_category: post_category,\n            post_user: post_user,\n            post_status: post_status,\n        }, success_redirect_url, '', 'preview_article');\n    });\n\n    function preview_article(response){\n        if (response.data.preview_url){\n            window.location.href=response.data.preview_url;\n        } else {\n            alert(response.msg);\n        }\n\n    }\n\n    $('.quick-release-option-button').on('click', function(){\n        let userInput = prompt(\"请鼠友输入快捷发布数量：\");\n\n        if (userInput == null) {\n            return;\n        }\n\n        let parsedNumber = parseFloat(userInput);\n        if (isNaN(parsedNumber)) {\n            alert(\"鼠友请输入有效的数字！\");\n            return;\n        }\n\n        if (parsedNumber > 100){\n            alert(\"鼠友请少发点，服务器会有压力！\");\n            return;\n        }\n\n        let option_id = $(this).attr('data-value');\n\n        ajax_import_data_request_tool(request_url, {\n            action_func: 'option_publish',\n            option_id: option_id,\n            count: parsedNumber,\n        }, success_redirect_url);\n    });\n\n\n    /**\n     * style\n     */\n    if ($('input[type=radio][name=collect_type]:checked').val() == 'single'){\n        $('.collect_type_radio_change').hide();\n    }\n\n    $('#todo—more-button').on('click', function(){\n        $('.todo-more-show').attr(\"style\",\"display:block;\");\n    });\n\n    $('#keywords_default').on('click', function(){\n        $('textarea[name=\"collect_keywords\"]').html('[\\n' +\n            '    {\"count\":\"1\", \"title\":\"胖鼠\"},\\n' +\n            '    {\"count\":\"2\", \"title\":\"胖鼠采集\", \"link\":\"https://www.fatrat.cn\"}\\n' +\n            ']');\n    });\n\n    $('input[type=radio][name=collect_type]').change(function () {\n        if (this.value == 'list') {\n            $('.collect_type_radio_change').show();\n            console.log(1);\n        }\n        else if (this.value == 'single') {\n            $('.collect_type_radio_change').hide();\n            console.log(2);\n        }\n    });\n\n    $('.release_type').change(function () {\n        var choose = $('.release_type option:checked').val();\n        $('.release_type_change').each(function () {\n            if ($(this).attr('data-value') == choose){\n                $(this).show();\n            } else {\n                $(this).hide();\n            }\n        });\n    });\n\n    /**\n     * validation\n     */\n    $('.frc-activation').on('click', function(){\n        var activation_action = $(this).attr('data-value');\n        var activation_code = $('input[name=\"'+activation_action+'\"]').val();\n        if (activation_code != ''){\n            alert('请联系胖鼠激活');\n            return;\n        }\n        ajax_validation_request_tool(request_url, {\n            action_func: 'activation',\n            activation_action: activation_action,\n            activation_code: activation_code,\n        }, success_redirect_url);\n    });\n\n\n    $('.frc-function-switch').on('click', function(){\n        var switch_action = $(this).attr('data-value');\n\n        ajax_validation_request_tool(request_url, {\n            action_func: 'function_switch',\n            switch_action: switch_action,\n        }, success_redirect_url);\n    });\n\n\n    $('.debugging-click').on('click', function(){\n        var debugging_add=$(\".debugging-add\").show();\n        setTimeout(function(){\n            debugging_add.hide()\n            ajax_validation_request_tool(request_url, {\n                action_func: 'debugging_top_up',\n            });\n        },6000);\n\n    });\n\n\n    /**\n     * tool function\n     *\n     * request_tool 方法均可以使用回调函数\n     */\n    $('.frc_mysql_upgrade').on('click', function () {\n        var progress = $(this).attr('data-value');\n\n        ajax_option_request_tool(request_url, {\n            action_func: 'upgrade',\n            progress: progress,\n        }, success_redirect_url);\n    });\n\n\n\n    var frc_play_flag = false;\n    $('#wp-frc-data-play').on('click', function () {\n\n\n        let option_id = $(this).data(\"option_id\");\n        let text = $(this).val();\n        if (text == \"play\")\n        {\n            // let cookie = prompt('请随便打开一篇微信文章并粘贴cookie到此对话框:', '');\n            // //启动\n            // if (cookie != null) {\n                if(!confirm(\"需要停止时请再次点击此按钮\")){\n                    return;\n                }\n                $(this).val(\"stop\");\n                collect_play_timer = setInterval(function (){\n                    if (frc_play_flag) return true;\n                    frc_play_flag = true\n                    ajax_import_data_request_tool(request_url, {\n                        action_func: 'history_wait_play',\n                        option_id: option_id,\n                        // cookie:cookie\n                    },\"\",success_redirect_url,'change_frc_play_flag');\n                },3000)\n            // }\n        }else{\n            //停止\n            clearInterval(collect_play_timer);\n            alert('已经停止');\n            location.reload();\n            return true;\n        }\n    });\n\n    function change_frc_play_flag()\n    {\n        frc_play_flag = false\n    }\n\n    function ajax_collect_request_tool(request_url, data, progress_bar = '', input_disabled = '') {\n        // console.log(request_url, data, progress_bar, input_disabled);\n\n        $.ajax(request_url, {\n            method: 'POST',\n            dataType: 'json',\n            data: $.extend({action: 'frc_interface', interface_type: 1,csrf:$(\"#wp-frc-csrf\").val()}, data),\n            beforeSend : function(){\n                if (progress_bar != ''){\n                    $(progress_bar).css('width', '20%');\n                    setTimeout(function() {\n                        $(progress_bar).css('width', '40%');\n                    }, 1000);\n                    setTimeout(function() {\n                        $(progress_bar).css('width', '60%');\n                    }, 2000);\n                    setTimeout(function() {\n                        $(progress_bar).css('width', '80%');\n                    }, 3000);\n                }\n                if (input_disabled != ''){\n                    $(input_disabled).attr('disabled', 'disabled');\n                }\n            },\n            success: function(response) {\n                console.log(response);\n                if (progress_bar != ''){\n                    $(progress_bar).css('width', '100%');\n                }\n                setTimeout(function() {\n                    if (response.code == 200) {\n                        alert(response.msg);\n                    } else {\n                        alert('错误: '+response.msg);\n                    }\n                }, 500);\n            },\n            complete: function() {\n                setTimeout(function() {\n                    if (progress_bar != ''){\n                        $(progress_bar).css('width', '0%');\n                    }\n                }, 2000);\n                setTimeout(function() {\n                    if (input_disabled != ''){\n                        $(input_disabled).removeAttr('disabled');\n                    }\n                }, 2000);\n            },\n            error: function(error) {\n                alert('网络超时! 如果你点击后立刻出现此错误那是你的采集规则写错了,请排查规则错误. 如果你已经等待采集了很久, 那就是正常的网络超时哦. 去数据中心看看是不是已经下载好了.');\n                if (progress_bar != ''){\n                    $(progress_bar).css('width', '0%');\n                }\n                if (input_disabled != ''){\n                    setTimeout(function() {\n                        $(input_disabled).removeAttr('disabled');\n                    }, 10000);\n                }\n                console.log('error:', error);\n            }\n        });\n    }\n\n    function ajax_option_request_tool(request_url, data, success_redirect_url = '', error_redirect_url = ''){\n        // console.log(request_url, data);\n\n        $.ajax(request_url, {\n            method: 'POST',\n            dataType: 'json',\n            data: $.extend({action: 'frc_interface', interface_type: 2,csrf:$(\"#wp-frc-csrf\").val()}, data),\n            success: function(response) {\n                // console.log(response);\n                if (response.code == 200) {\n                    alert(response.msg);\n                    if (success_redirect_url != ''){\n                        window.location.href=success_redirect_url;\n                    }\n                } else {\n                    alert('错误: '+response.msg);\n                    if (error_redirect_url != ''){\n                        window.location.href=error_redirect_url;\n                    }\n                }\n            },\n            error: function(error) {\n                alert('Network Error !');\n                console.log('Network Error !:', error)\n            }\n        })\n    }\n\n    function ajax_import_data_request_tool(request_url, data, success_redirect_url = '', error_redirect_url = '', callback = ''){\n        // console.log(request_url, data);\n\n        $('.request—loading').addClass('fa-spin');\n        $.ajax(request_url, {\n            method: 'POST',\n            dataType: 'json',\n            data: $.extend({action: 'frc_interface', interface_type: 3,csrf:$(\"#wp-frc-csrf\").val()}, data),\n            success: function(response) {\n                // console.log(response);\n                $('.request—loading').removeClass('fa-spin');\n                if (response.code == 200) {\n                    if (callback != ''){\n                        eval(callback+\"(response)\");\n                        return ;\n                    }\n                    alert(response.msg);\n                    if (success_redirect_url != ''){\n                        window.location.href=success_redirect_url;\n                    }\n                } else {\n                    alert('错误: '+response.msg);\n                    if (error_redirect_url != ''){\n                        window.location.href=error_redirect_url;\n                    }\n                }\n            },\n            error: function(error) {\n                $('.request—loading').removeClass('fa-spin');\n                alert('Network Error !');\n                console.log('Network Error !:', error)\n            }\n        });\n    }\n\n    function ajax_validation_request_tool(request_url, data, success_redirect_url = '', error_redirect_url = ''){\n        // console.log(request_url, data);\n\n        $.ajax(request_url, {\n            method: 'POST',\n            dataType: 'json',\n            data: $.extend({action: 'frc_interface', interface_type: 4,csrf:$(\"#wp-frc-csrf\").val()}, data),\n            success: function(response) {\n                if (response.code == 200) {\n                    alert(response.msg);\n                    if (success_redirect_url != ''){\n                        window.location.href=success_redirect_url;\n                    }\n                } else {\n                    alert('错误: '+response.msg);\n                    if (error_redirect_url != ''){\n                        window.location.href=error_redirect_url;\n                    }\n                }\n            },\n            error: function(error) {\n                alert('Network Error !');\n                console.log('Network Error !:', error)\n            }\n        })\n    }\n\n})(jQuery);"
  },
  {
    "path": "readme.txt",
    "content": "=== 胖鼠采集(Fat Rat Collect) ===\nContributors: fbtopcn\nDonate link: https://www.fatrat.cn/docs/v2/bounty\nTags: 采集,微信公众号文章采集,知乎采集,列表采集,批量采集\nRequires at least: 4.6\nTested up to: 6.7\nStable tag: 2.7.5\nRequires PHP: 7.2\nLicense: GPLv2 or later\nLicense URI: https://www.gnu.org/licenses/gpl-2.0.html\n\n胖鼠采集(Fat Rat Collect) 是一款能够帮助你网站自动化的采集工具. 支持采集、微信、简书、知乎、自定义列表页、自定义详情页面、还有许多特色功能、 还可一键采集历史文章, 一键设置自动采集, 自动发布, 为您节省精力, 快来体验一下吧!\n\n== Description ==\n胖鼠采集(<a href=\"https://www.fatrat.cn\" target=\"_blank\">Fat Rat Collect</a>) 是一款能够帮助你网站自动化的采集工具. 开源作品, 支持采集所有网站列表及详情页面 它拥有微信、简书、知乎、列表、历史、详情、等多种采集方式、还有自动采集, 自动发布, 自动打标签, 等许多黑科技功能, 一次创建规则, 后续省心省力. 还有许多演示例子，一键可用。如: 微信、简书、知乎、御龙在天、寻仙、虎扑等许多例子、快去享受吧!\n\n= 神奇之处 =\n* 微信公众号文章采集 - 强大的Jquery可以处理各种版权信息, 纵享丝滑.\n* 简书文章采集 - 强大的Jquery可以处理内容各种图片, 柔顺到底.\n* 知乎问答采集 - 强大的Jquery可以处理各种你不想要的东西, 一键爽歪歪.\n* (独家主打) 列表采集，历史采集 <a href=\"https://www.fatrat.cn/docs/v2/list-paging-collection\" target=\"_blank\">视频文字教程</a>- 只需轻轻一点. 数不清的文章就来了.\n* (独家主打) 详情页面文章采集 - 任何网站十秒搞定\n* (独家主打) <a href=\"https://www.fatrat.cn/docs/v2/list-paging-collection\" target=\"_blank\">分页爬取</a> - 历史数据, 也不放过. 一网打尽\n* (胖鼠主打) 自动采集 - 一键启动不放过每一份数据.\n* (胖鼠主打) 自动发布 - 您省心省力好帮手.\n* (独家主打) 调试模式 - 新建规则好帮手, 采集结果好伙伴.\n* (独家主打) 体验例子 - 一键体验胖鼠.\n* (主打主打) 文章自动添加, <a href=\"https://www.fatrat.cn/docs/v2/dynamic-content\" target=\"_blank\">动态内容</a>, <a href=\"https://www.fatrat.cn/docs/v2/auto-tags\" target=\"_blank\">自动标签</a>, 标签内链, 优化SEO.\n* (胖鼠采集) 文章滤重 - 支持.\n* (胖鼠采集) 自动特色图片 - 支持.\n* (胖鼠采集) 采集图片加入媒体库 - 支持.\n* (胖鼠采集) 数据处理 - 完美支持Html Jquery\n* (胖鼠采集) 内容关键字过滤替换 伪原创 - 支持.\n* (胖鼠采集) 自定义采集任何可见网站 - 完美支持.\n* (胖鼠采集) 自定义文章图片链接类型 - 支持.\n* (胖鼠采集) 内容详情页数据分页采集 - 支持.\n* (胖鼠采集) 关键词随机插入, 可指定关键词或A标签关键词随机插入文章正文中 - 支持.\n* (胖鼠采集) 图片本地下载, 支持使用其他插件上传(阿里云OSS、又拍云云存储, 七牛对象存储), 并可突破图片防盗链.\n* (胖鼠采集) 相比其它采集器如: 火车头、神箭手、后羿、八爪鱼、以及一些伪原创采集工具, 胖鼠采集简单易用, 功能强大，是您建站的好帮手\n* (重磅重磅) 胖鼠采集完全基于Wordpress, 安装即用, 开源作品\n* (声明声明) 如你的PHP版本小于PHP71, 请移步胖鼠采集的Github下载使用胖鼠v5版本 分支名: based_php_5.6, 不再更新v5版本，不推荐\n* (声明声明) 胖鼠采集初衷为参考学习交流; 请大家遵纪守法. 抵制违法犯罪.\n* (声明声明) 胖鼠采集开源可供您查阅代码, 或者二次开发使用供您使用, 但不可修改源码后用于商业行为.\n\n= 胖鼠采集系统架构 =\n* 系统分为五大块.\n* ① 采集中心, 配置各种特色配置来采集数据.\n* ② 配置中心, 为采集中心提供采集规则.\n* ③ 数据桶,   数据管理中心 此模块控制采集数据.\n* ④ Debugging, 此模块用于大家调试规则.\n* ⑤ 胖鼠工具箱, 此模块是胖鼠特色小功能.\n\n= 使用谨记 =\n* 采集是一件极其消耗系统资源的事情，尤其是图片下载。\n* 新鼠友, 可一键体验例子. 例子运行正确, 那就专心写规则吧.\n* 本工具仅供学习参考, 作者不承担任何风险.\n\n== Installation ==\n\n安装：\n1. 在插件中搜索 <strong>胖鼠采集</strong> 安装即可\n2. 将插件文件上传到/wp-content/plugins/目录 即可\n3. PHP版本小于PHP71, 请移步胖鼠采集的Github下载使用胖鼠v5版本 分支名: based_php_5.6\n\n== Frequently Asked Questions ==\n\n= 胖鼠FAQ =\n采集成功, 但是没有数据? 右键检查 console 中有调试信息, 可供您参考\n胖鼠采集收费吗？只有特色功能收费，列表采集、历史采集。自动采集、自动发布 等核心功能均免费\n微信公众号历史采集支持吗？暂不支持\najax页面采集支持吗？赞助可支持\n图片可以下载吗？ 可以, 还可设置图片路径格式\n链接相对路径可以补全吗？ 可以\n\n= 关于新建配置 =\n请多多使用debuggging功能\n配合视频、文字教程、助您成功\n\n\n= 胖鼠推荐服务环境 =\nphp推荐 使用php72及以上版本\n推荐使用 nginx\n推荐使用 mysql 5.7\n推荐及时更新胖鼠采集\n\n== Screenshots ==\n1. 胖鼠强大的爬虫中心\n2. 支撑胖鼠的配置中心\n3. 发布文章的数据桶\n4. 添加修改配置地方\n5. 调试中心debugging\n6. 工具箱特色小工具\n\n== Changelog ==\n\n= 2.7.4\n* 配合官方安全更新\n\n= 2.7.3\n* 修复公众号采集的一个BUG\n\n= 2.7.2\n* 修复公众号采集的重新激活BUG\n\n= 2.7.1\n* 修复一个影响新鼠友的保存配置的BUG\n\n= 2.7.0\n* 微信公众号历史文章采集\n* 登陆网站 cookie 采集\n\n= 2.6.7/8\n* 优化一些安全相关问题\n\n= 2.6.6\n* 优化提示文案\n* 修复自动发布快捷发布故障\n* 快捷发布增加批量发布功能（新功能）\n\n= 2.6.5\n* 安全更新，性能优化\n* 全站采集保存正则BUG修复\n\n= 2.6.3\n* 安全更新\n* 代码优化\n\n= 2.6.2\n* 安全优化\n\n= 2.6.1\n* 修复采集列表或者分页的时候，被目标站防采集命中，会出现的采集数据的url不一致、但是数据的标题以及内容和源网站不一样，数据会重复的bug\n\n= 2.6.0\n* 升级组件，兼容PHP8\n* 修复数据桶分页数量bug\n* 修复自动采集html展示问题\n* 修复配置数量为5个无法编辑问题\n* 优化文案\n* 优化项目结构\n* 使用composer自动加载\n\n= 2.5.2\n* 修复关键词随机插入保存错误\n\n= 2.5.1\n* 部分语法兼容php8\n* 数据桶样式优化\n* 配置中心文章正文添加头尾html反斜线bug\n\n= 2.5.0\n* 升级 bootstrap\n\n= 2.4.4\n* 官方指导、代码修正, 写法规范.\n* 简单而又大量的优化.\n* 修复oss图片上传相对地址选项，但站点根目录不是 wp-content 会出现的bug.\n\n= 2.4.3\n* 修复关键词替换的BUG\n\n= 2.4.2\n* 修复新鼠友安装后无法保存配置Bug.\n\n= 2.4.1\n* 数据表字段长度调整\n* 代码精简\n\n= 2.4.0\n* 新增关键词插入功能, 可设置一批关键词随机插入文章正文段落中.\n* 修复一个分页的历史遗留bug, 可输出单页页码进行采集\n* 分页采集改为一次可采集3页\n* 优化了代码\n\n= 2.3.0\n* Optimization Absolute Url.\n* 增加内容分页采集功能.\n\n= 2.2.6\n* Fix Auto Absolute Url Bug.\n\n= 2.2.5\n* 修复bug，提升稳定性\n\n= 2.2.3-4\n* 修复自动发布 动态内容，自动标签bug\n* 优化代码，提升速度\n\n= 2.2.1-2\n* 微信采集链接优化\n* 优化了软件速度\n\n= 2.2.0\n* 主题发布扩展\n* 图片下载上传对接oss/云存储优化\n* 去除html注释\n* 文章发布优化\n* 数据统计优化\n* 取消特色图片激活\n* 采集优化、最大超时时间10秒\n* 删除规则，删除对应数据\n* 等其他优化..\n\n= 2.1.0\n* 采集底层内存占用重构, 鼠友的福音\n* 批量发布使用设置的发布状态\n\n= 2.0.7\n* 优化速度 .\n\n= 2.0.6\n* fix bug .\n* 插件提升管理员权限使用.\n\n= 2.0.5\n* 采集图片路径优化/优化window主机附件无法查看\n* 代码小版本迭代\n* 数据入库优化代码，优化速度\n* 批量删除细节优化\n\n= 2.0.4\n* 数据链接优化\n\n= 2.0.3\n* 优化插件速度，精简很多地方.\n\n= 2.0.2\n* 低版本数据库兼容\n\n= 2.0.1\n* 大数据量鼠优化升级步骤\n\n= 2.0.0 = 2020-04-26\n* 《胖鼠采集架构重组升级》\n* 定时采集、定时发布强化\n* 数据中心升级为数据桶模式、可设置数据桶对应发布分类\n* 自动标签强化，标签匹配英文不区分大小写, 后续继续优化\n* 动态内容强化样式。新版只在尾部添加动态内容, 后续继续优化\n* 新增标签添加网站内链、5.1日前赞赏过自动标签用户免费激活\n* 采集 & 调试\n* 增加采集知乎问答功能\n* 微信、简书、列表、详情、分页采集增加 debugging 功能\n* 点击采集、异常后、按钮延时优化，避免不必要的问题\n* 采集实体字符转义一些问题\n* 文章重复问题优化、目前为url验重、后续增加文章标题验证重复\n* 图片本地化功能加强升级\n* 分页采集加强升级\n* debug 全新升级 debugging\n* 采集Url格式化升级\n* 优化列表采集点击锚点体验\n* 接口结果统一优化\n* 采集数据可删除、批量管理\n* 数据桶全局统计数据，所有数据一手掌握\n\n= 1.11.1 = 2019-11-30\n* delete Violations wordpress keywords\n\n= 1.11.1 = 2019-09-19\n* 简书规则升级\n\n= 1.11.0 = 2019-09-04\n* 优化了很多代码\n* 增加图片不本地化选项。(采集速度超快)\n* 可指定采集图片的属性。(对于某些js异步加载图片的站点很有效)\n\n= 1.10.4 = 2019-06-12\n* 优化一些地方\n\n= 1.10.3 = 2019-05-19\n* 优化 Dynamic Content 功能, 优化了取文字样式\n* 优化 Auto Tags 功能, 暂时去掉了标签追加链接功能, 有bug回头解决了再加\n* 数据中心弱网发布时间优化\n\n= 1.10.2 = 2019-05-05\n* 优化 Dynamic Content 功能\n* 优化 Auto Tags 功能\n* Auto Tags 功能 增加开关和一些优化\n\n= 1.10.1 = 2019-05-04\n* 代码优化\n\n= 1.10.0 = 2019-05-04\n* 新功能 Dynamic Content\n\n= 1.9.0 = 2019-05-03\n* 新功能 Auto Tags 文章自动打Tag or 优化一些文案\n\n= 1.8.7 = 2019-04-30\n* 修复一个紧急bug\n\n= 1.8.6 = 2019-04-29\n* 文章滤重改为强滤重\n* 数据表增加一项字段\n* 一次发布最大数量增加到30\n\n= 1.8.4 = 2019-04-23\n* 优化 据个别鼠要求, 采集标题 增长为120个汉字\n* 优化 采集保存配置一点逻辑优化\n* 文案优化\n\n= 1.8.3 = 2019-04-15\n* 优化 采集标题可能超过40个汉字长度 控制在40个字符之内\n* 优化 下载图片可能会超时优化了连接时间\n* 优化 一次发布很多篇, 极端情况可能图片超时问题\n* 优化 发布文章个别情况可能出现报错, 捕获错误\n* 优化 文章别名, 使用文章标题作为文章别名\n* 新增 公告功能: 用于胖鼠紧急通知众鼠使用, 无风险。\n* 新增 微信增加 作者变量{author} 公众号名字变量{name} 简书增加作者变量{author}\n\n= 1.8.2 = 2019-04-14\n* 修复了 一个不影响大局的sql错误\n\n= 1.8.1 = 2019-04-14\n* 修复 微信 简书 采集失败bug\n\n= 1.8.0 = 2019-04-14\n* 胖鼠采集全新架构\n* window主机用户采集微信图片 鼠友服务器CA证书验证不通过问题\n* window主机 路径 DIRECTORY_SEPARATOR 可能出现的bug\n* 采集内核2.0。更快的采集速度。 (3.0规划已有。采集速度会超级超级快)\n* 采集图片自动查找后缀算法优化\n* 自动特色图片功能完成\n* 图片加入媒体库功能\n* 图片加入附件\n* 发布时图片发布失败。补二次下载\n\n= 1.7.5 = 2019-04-09\n* 修复了几位鼠友用window服务器出现的图片路径乱码bug\n\n= 1.7.4 = 2019-03-31\n* 修复了简书图片bug\n* 数据中心增加数据统计功能\n\n= 1.7.3 = 2019-03-08\n* 冒泡\n\n= 1.7.2 = 2019-02-25\n* 修复群里一个鼠友采集图片失败的bug.\n* 升级群里鼠友采集的图片默认居中需求.\n\n= 1.7.1 = 2019-02-15\n* 胖鼠采集PHP v5.6 版本尝鲜版发布.\n* 优化一些文案.\n\n= 1.7.0 = 2019-01-25\n* 定时发布 (给鼠友增加开关）\n* 定时采集 (给鼠友增加开关）\n* 图片可设置使用 相对/绝对 路径. 站群/单站点/CDN可能要的需求\n* 微信采集自定义内容(鼠友要求可增加来源)\n* 免责声明\n\n= 1.6.3 = 2019-01-24\n* 鼠友发现采集的微信视频无法播放BUG!\n\n= 1.6.2 = 2019-01-22\n* 微信 And 列表采集 图片 自动剔除多余属性 增加 Alt字段 值为title 更好的SEO!\n\n= 1.6.1 = 2019-01-21\n* 一个安全过滤误伤了鼠友. 已修复\n* 版本号修正\n\n= 1.6.0 = 2019-01-20\n* Php版本验证提示\n* 配置中心批量删除\n* 数据中心可能出现的一个notice错误\n* 数据发布,增加发布作者,文章状态.\n* 数据中心作者字段优化\n* 赞赏码\n\n= 1.5.1 = 2019-01-15\n* 帮助的a 标签跳转新开标签页\n* 增加自动发布tag页面\n* 新增加的文档的链接\n* 分页采集增加默认select\n* 修复自动爬去功能异常\n* Css Js样式 兼容了其他插件\n* 修复一个列表爬虫。由于目标站不统一。链接可能拼接错误bug\n\n= 1.5.0 = 2019-01-13 11:16\n* 优化配置中心一个 notice 错误\n* 增加了数据批量删除\n* 增加数据批量发布\n* 文章增加发布分类\n* 使用权限增加作者 编辑 管理员\n\n= 1.4.3 = 2019-01-03 10:39\n* ok 优化了详情爬虫, 增加了默认选项\n* ok 增加了几个采集配置 寻仙新闻 御龙在天新闻 心理咨询师新闻 直播吧详情 虎扑详情\n* ok 优化了前端错误提示\n* 有个个别网站 gbk 个别乱码问题/未解决。utf-8很稳定\n* 今天关闭了站群自动发布,自动发布什么时候再次开启?\n\n= 1.4.2 = 2019-01-02\n* 暂时去掉站群发布页面\n* 去掉了一些默认配置规则，后续增加\n* 采集url地址 代码优化\n\n= 1.4.1 = 2019-01-01 11:05\n* 增加了小提示功能.等你发现在哪里.\n* 增加了简书采集\n* 捕获简书新的图片src, 调整了代码\n\n= 1.4.0 = 2018-12-30 03:09\n* 跳几个小版本, 因为这次是一个架构稳定版本(稳)\n* 新增自定义详情爬取\n* 自动识别 img (src or data-src)\n* 配置页面优化 注释优化 服务端优化\n* 发布中心优化服务端 页面优化\n* 爬虫中心 服务端优化 前端优化\n* 前端ajax交互优化\n* 数据库优化了表，增加了索引\n* 优化掉了Log表\n* ...\n\n= 1.0.0 = 2018-12-20\n* 胖鼠第一个版本上线了 不写了 具体的功能了 信息量有点大。大家自己安装感受一下具体功能吧。\n\n== Upgrade Notice ==\n\n"
  },
  {
    "path": "src/Controller/TaskController.php",
    "content": "<?php\n/**\n * Copyright (c) 2018-2020 Fat Rat Collect . All rights reserved.\n * 胖鼠采集 WordPress最好用的采集插件.\n * GitHub: https://github.com/KitePig/FatRat-Collect\n * @Author KitePig\n * @CreateTime: 2022年04月11日 03:05\n */\n\nif (!class_exists('WP_List_Table')) {\n    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');\n}\nclass TaskController extends WP_List_Table\n{\n    protected $wpdb;\n    protected $table_post;\n\n    public function __construct()\n    {\n        parent::__construct();\n        $this->wpdb = getDb();\n        $this->table_post = $this->wpdb->prefix . 'frc_post';\n    }\n\n    public function prepare_items()\n    {\n        $columns = $this->get_columns();\n        $hidden = array();\n        $sortable = $this->get_sortable_columns();\n\n        //Retrieve $customvar for use in query to get items.\n        $customvar = frc_sanitize_text('customvar', 'total');\n        $this->_column_headers = array($columns, $hidden, $sortable);\n\n        $this->process_bulk_action();\n        $this->views();\n        $per_page = $this->get_items_per_page('snippets_per_page', 10);\n        $current_page = $this->get_pagenum();\n        $total_items = self::record_count();\n\n        $this->set_pagination_args(array(\n            'total_items' => $total_items,\n            'per_page' => $per_page,\n        ));\n\n        $this->items = self::get_snippets($per_page, $current_page, $customvar);\n    }\n\n    public function process_bulk_action()\n    {\n        // If the delete bulk action is triggered\n        if (\n            ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) ||\n            ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] )\n        ) {\n//            $delete_ids = esc_sql( $_POST['snippets'] );\n//\n//            // loop over the array of record IDs and delete them\n//            foreach ( $delete_ids as $id ) {\n//                $this->delete_snippet( $id );\n//            }\n//\n//            return;\n        }\n    }\n\n    public function get_columns(): array\n    {\n        return array(\n            'cb' => /** @lang text */ '<input type=\"checkbox\" />',\n            'id' => esc_html__('ID', 'Fat Rat Collect'),\n            'collect_name' => esc_html__('配置名称', 'Fat Rat Collect'),\n            'collect_describe' => esc_html__('配置描述', 'Fat Rat Collect'),\n            'collect_type' => esc_html__('采集类型', 'Fat Rat Collect'),\n            'collect_list_url' => esc_html__('采集地址', 'Fat Rat Collect'),\n            'collect_image_download' => esc_html__('下载图片', 'Fat Rat Collect'),\n            'collect_image_path' => esc_html__('图片使用路径', 'Fat Rat Collect'),\n            'collect_image_attribute' => esc_html__('目标图片源属性', 'Fat Rat Collect'),\n            'created_at' => esc_html__('创建时间', 'Fat Rat Collect'),\n        );\n    }\n\n    public function get_sortable_columns(): array\n    {\n        return array(\n            'id' => array('id', false),\n        );\n    }\n\n    public static function get_snippets($per_page = 10, $page_number = 1, $customvar = 'total')\n    {\n        $model = new FRC_Options();\n        $result = $model->options_paging($page_number, $per_page, $customvar);\n        return collect($result)->map(function ($data){\n            $data['collect_auto_collect'] = '完善中';\n            $data['collect_auto_release'] = '完善中';\n            return $data;\n        });\n    }\n\n    public static function record_count($customvar = 'total')\n    {\n        $model = new FRC_Options();\n        return $model->record_count($customvar);\n    }\n\n    public function view()\n    {\n        $snippet_obj = new self();\n        ?>\n\n            <div class=\"wrap\">\n                <h1><?php esc_html_e( '任务中心', 'Fat Rat Collect' ) ?>\n                    <?php if (!empty(get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP))) { ?>\n                        <img width=\"20\" src=\"<?php frc_image('fat-rat-nav-v-yellow.png') ?>\" />\n                    <?php } ?>\n                    <a href=\"<?php esc_attr_e(admin_url( 'admin.php?page=frc-tasks' )); ?>\" class=\"page-title-action\"><?php _e( '新建采集任务', 'Fat Rat Collect' ) ?></a>\n                </h1>\n                <div><span style=\"color: #ff3d00;\"><?php _e(((new FRC_Validation())->announcement('notice-tasks'))); ?></span></div>\n                <input type=\"hidden\" hidden id=\"success_redirect_url\"\n                       value=\"<?php esc_attr_e(admin_url('admin.php?page=frc-tasks')); ?>\">\n\t            <?php require_once(plugin_dir_path(__DIR__) . 'views/csrf.php'); ?>\n                <form method=\"post\">\n                    <input type=\"hidden\" hidden id=\"request_url\" value=\"<?php esc_attr_e(admin_url('admin-ajax.php')); ?>\">\n                    <?php\n                    $snippet_obj->prepare_items();\n                    $snippet_obj->display();\n                    ?>\n                </form>\n            </div>\n        <?php\n    }\n}"
  },
  {
    "path": "src/Helpers/helpers.php",
    "content": "<?php\n\nif (!function_exists(\"startsWith\")) {\n    /**\n     * Determine if a given string starts with a given substring.\n     *\n     * @param string $haystack\n     * @param string|string[] $needles\n     * @return bool\n     */\n    function startsWith(string $haystack, $needles): bool\n    {\n        foreach ((array)$needles as $needle) {\n            if ((string)$needle !== '' && str_starts_with($haystack, $needle)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n\nif (!function_exists(\"frc_sanitize_text\")) {\n    /**\n     * Function to sanitize $_REQUEST data\n     * @param string $key\n     * @param ?string $default\n     * @return ?string\n     */\n    function frc_sanitize_text(string $key, ?string $default = ''): ?string\n    {\n        if (isset($_REQUEST[$key]) && !empty($_REQUEST[$key])) {\n            return sanitize_text_field($_REQUEST[$key]);\n        }\n\n        return $default;\n    }\n}\n\nif (!function_exists(\"frc_sanitize_textarea\")) {\n    /**\n     * Function to sanitize $_REQUEST data\n     * @param string $key\n     * @param ?string $default\n     * @return ?string\n     */\n    function frc_sanitize_textarea(string $key, ?string $default = ''): ?string\n    {\n        if (isset($_REQUEST[$key]) && !empty($_REQUEST[$key])) {\n            return sanitize_textarea_field(htmlspecialchars($_REQUEST[$key]));\n        }\n\n        return $default;\n    }\n}\n\nif (!function_exists(\"frc_sanitize_array\")) {\n    /**\n     * Function to sanitize strings within $_REQUEST data arrays\n     * @param string $key\n     * @param string $type\n     * @return array\n     */\n    function frc_sanitize_array(string $key, string $type = 'integer' ): array\n    {\n        if ( isset($_REQUEST[ $key ]) && ! empty( $_REQUEST[ $key ] ) ) {\n\n            if ( ! is_array( $_REQUEST[ $key ] ) ) {\n                return [];\n            }\n\n            if ( 'integer' === $type ) {\n                return array_map( 'absint', $_REQUEST[ $key ] );\n            } else { // strings\n                $array = array();\n                foreach ( $_REQUEST[ $key ] as $val ) {\n                    $array[] = sanitize_text_field( $val );\n                }\n                return $array;\n            }\n        }\n\n        return [];\n    }\n}\n\nif (!function_exists(\"frc_option_esc_attr_e\")) {\n    /**\n     * @param $option\n     * @param $key\n     * @param string $default\n     */\n    function frc_option_esc_attr_e($option, $key, string $default = '')\n    {\n        if (isset($option) && isset($option[$key])) {\n            esc_attr_e($option[$key]);\n            return;\n        }\n\n        _e($default);\n    }\n}\n\nif (!function_exists(\"translationRules\")) {\n    /**\n     * @param $rules\n     * @return array\n     */\n    function translationRules($rules): array\n    {\n        $array = [];\n        if (empty($rules)){\n            return $array;\n        }\n        foreach (explode(')(', $rules) as $item){\n            list($key, $val) = explode('%', $item);\n            list($selector, $attribute, $filter) = explode('|', $val);\n            $array[$key] = [\n                'selector' => $selector === 'null' ? null : str_replace('\\\\', '', $selector),\n                'attribute' => $attribute === 'null' ? null : str_replace('\\\\', '', $attribute),\n                'filter' => $filter === 'null' ? null : str_replace('\\\\', '', $filter),\n            ];\n        }\n        return $array;\n    }\n}\n\nif (!function_exists(\"frcAddColumn\")) {\n    /**\n     * @param $column\n     * @param $alterColumnSql\n     * @param $table\n     */\n    function frcAddColumn($column, $alterColumnSql, $table): void\n    {\n        $wpdb = getDb();\n        $table = getTable($table);\n        //Check for Exclude Image Path\n        $checkColumn = $wpdb->get_results($wpdb->prepare(\n            \"SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s \",\n            DB_NAME, $table, $column\n        )) ;\n        if ( empty( $checkColumn ) ) {\n            $alterSql = \"ALTER TABLE `$table` ADD `{$column}` $alterColumnSql\";\n            $wpdb->query($alterSql);\n        }\n    }\n}\n\nif (!function_exists(\"frcChangeColumn\")) {\n    /**\n     * @param $sql\n     * @param $table\n     */\n    function frcChangeColumn($sql, $table): void\n    {\n        $table = getTable($table);\n        getDb()->query(\"ALTER TABLE $table $sql\");\n    }\n}\n\nif (!function_exists(\"getDb\")) {\n    /**\n     * @return wpdb\n     */\n    function getDb()\n    {\n        global $wpdb;\n\n        return $wpdb;\n    }\n}\n\nif (!function_exists(\"getTable\")) {\n    /**\n     * @param $table\n     * @return string\n     */\n    function getTable($table): string\n    {\n        global $wpdb;\n\n        if ($table == 'option'){\n            return $wpdb->prefix . 'frc_options';\n        }\n\n        if ($table == 'post'){\n            return $wpdb->prefix . 'frc_post';\n        }\n    }\n}"
  },
  {
    "path": "src/Helpers/helpers2.php",
    "content": "<?php\n\nif (!function_exists(\"randomInsertString\")) {\n    /**\n     * @param $txt\n     * @param $insert\n     * @return string\n     */\n    function randomInsertString($txt, $insert): string\n    {\n        preg_match_all(\"/[\\x01-\\x7f]|[\\xe0-\\xef][\\x80-\\xbf]{2}/\", $txt, $match);\n\n        $delay = array();\n        $add = 0;\n        foreach ($match[0] as $k => $v) {\n            if ($v == '<') $add = 1;\n            if ($add == 1) $delay[] = $k;\n            if ($v == '>') $add = 0;\n        }\n\n        $strArr = $match[0];\n        $len = count($strArr);\n\n        if (is_array($insert)) {\n            foreach ($insert as $k => $v) {\n                $insertk = insertK($len - 1, $delay);\n                $strArr[$insertk] .= $insert[$k];\n            }\n        } else {\n            $insertk = insertK($len - 1, $delay);\n            $strArr[$insertk] .= $insert;\n        }\n\n        return join('', $strArr);\n    }\n}\n\nif (!function_exists(\"insertK\")) {\n    /**\n     * @param $count\n     * @param $delay\n     * @return int\n     */\n    function insertK($count, $delay): int\n    {\n        $insertk = rand(0, $count);\n        if (in_array($insertk, $delay)) {\n            $insertk = insertK($count, $delay);\n        }\n        return $insertk;\n    }\n}"
  },
  {
    "path": "src/Service/AbsoluteUrl.php",
    "content": "<?php\n\nnamespace QL\\Ext;\n\nuse QL\\Contracts\\PluginContract;\nuse QL\\QueryList;\n\nclass AbsoluteUrl implements PluginContract\n{\n    public static function install(QueryList $queryList, ...$opt)\n    {\n        $queryList->bind('absoluteUrl',function ($config) use ($queryList){\n            return AbsoluteUrl::convertAll($queryList, $config);\n        });\n\n    }\n\n    public static function convertAll($ql, $config)\n    {\n        $ql->find('a')->map(function($item) use ($ql, $config){\n            $relativeUrl = $item->attr('href');\n            $item->attr('href', AbsoluteUrl::urlFormat($relativeUrl, $config->url));\n        });\n\n        $ql->setHtml(htmlspecialchars_decode($ql->find('')->html()));\n        return $ql;\n    }\n\n    public static function urlFormat($url, $domain){\n\n        if (empty($url) || empty($domain)){\n            return $url;\n        }\n\n        if (startsWith($url, \"http://\") ||\n            startsWith($url, \"https://\")){\n            return $url;\n        }\n\n        if (startsWith($url, \"//\")){\n            $domainFormat = parse_url($domain);\n\n            return isset($domainFormat['scheme']) ? $domainFormat['scheme'].':'.$url : 'http:'.$url;\n        }\n\n        if (startsWith($url, \"#\")){\n            return '';\n        }\n\n        if (startsWith($url, \"./\")){\n\t        return substr($domain, 0, strripos($domain, '/')) . ltrim($url, '.');\n        }\n\n        if (startsWith($url, \"../\")){\n            $base = substr($domain, 0, strripos($domain, '/'));\n            $base = substr($base, 0, strripos($base, '/'));\n            return $base . '/' . ltrim($url, '\\.\\./');\n        }\n\n        if (startsWith($url, \"/\")){\n            $domainFormat = parse_url($domain);\n\n            return $domainFormat['scheme'].'://'.$domainFormat['host'].'/'.ltrim($url, '/');\n        }\n\n        return substr($domain, 0, strripos($domain, '/')) . '/' . ltrim($url, '/');\n    }\n}\n"
  },
  {
    "path": "src/Service/DownloadImage.php",
    "content": "<?php\n\nnamespace QL\\Ext;\n\nuse QL\\Contracts\\PluginContract;\nuse QL\\QueryList;\n\nclass DownloadImage implements PluginContract\n{\n    public static function install(QueryList $queryList, ...$opt)\n    {\n        $queryList->bind('downloadImage',function ($config) use ($queryList){\n            return DownloadImage::downloadAll($queryList, $config);\n        });\n\n    }\n\n    public static function downloadAll($ql, $config)\n    {\n        if ($config->image_download == 3){\n             $ql->find('img')->remove();\n             return $ql;\n        }\n\n        $ql->find('img')->map(function($item) use ($ql, $config){\n            $imageUrl = $item->attr($config->src);\n            if (empty($imageUrl)){ return $item; }\n            $imageUrl = AbsoluteUrl::urlFormat($imageUrl, $config->url);\n\n            if ($config->image_download == 2){\n                $item->removeAttr('*');;\n                $item->attr('src', $imageUrl);\n            } else {\n                // image_download = 1/4\n                try {\n                    $name = 'frc-' . md5($imageUrl) . DownloadImage::suffix($imageUrl);\n                    $wp_upload_dir = wp_upload_dir();\n                    $wp_upload_dir_path = $wp_upload_dir['path'];\n                    if ($config->image_path == 1){\n                        $imageUrlPath = $wp_upload_dir_path . DIRECTORY_SEPARATOR . $name; // 实际路径用 DIRECTORY_SEPARATOR\n                        $imageUrlWeb = $wp_upload_dir['url'] . '/' . $name; // 拼接必须用 /\n                    } else {\n                        // 本地存储图片，开启oss会覆盖配置, 需要用default\n                        $wp_upload_web_url = $wp_upload_dir['url'];\n                        if (isset($wp_upload_dir['default']['path'])){\n                            $wp_upload_dir_path = $wp_upload_dir['default']['path'];\n                            $wp_upload_web_url = $wp_upload_dir['default']['url'];\n                        }\n                        $imageUrlPath = $wp_upload_dir_path . DIRECTORY_SEPARATOR . $name; // 实际路径用 DIRECTORY_SEPARATOR\n                        $imageUrlWeb = str_replace(site_url(), '', $wp_upload_web_url) . '/' . $name;\n                        // $imageUrlWeb = strstr($wp_upload_dir_path, '/wp-content/') . '/' . $name; 解决目录非 wp-admin 使用本地图片问题\n                    }\n\n                    if (!file_exists($imageUrlPath)){\n                        $http = new \\GuzzleHttp\\Client();\n                        $data = $http->request('get', $imageUrl, ['verify' => false])->getBody()->getContents();\n                        file_put_contents($imageUrlPath, $data);\n                    }\n\n                    $item->removeAttr('*');\n                    $item->attr('src', $imageUrlWeb);\n                } catch (\\Exception $e) {\n                    // 失败掠过.\n                }\n            }\n\n            return $item;\n        });\n\n        return $ql;\n    }\n\n    public static function suffix($path){\n\n        $suffix = '.jpg'; // 默认一个值\n        if (in_array(strtolower(strrchr($path, '.')), ['.jpg', '.png', '.jpeg', '.gif', '.swf'])) {\n            $suffix = strrchr($path, '.');\n        } else {\n            switch (getimagesize($path)[2]) {\n                case IMAGETYPE_GIF:\n                    $suffix = '.gif';\n                    break;\n                case IMAGETYPE_JPEG:\n                    $suffix = '.jpeg';\n                    break;\n                case IMAGETYPE_PNG:\n                    $suffix = '.png';\n                    break;\n                case IMAGETYPE_SWF:\n                    $suffix = '.swf';\n                    break;\n            }\n        }\n\n        return $suffix;\n    }\n\n}"
  },
  {
    "path": "src/Service/GetTransCoding.php",
    "content": "<?php\n\nnamespace QL\\Ext;\n\nuse QL\\Contracts\\PluginContract;\nuse QL\\QueryList;\n\nclass GetTransCoding implements PluginContract\n{\n    public static function install(QueryList $queryList, ...$opt)\n    {\n        $queryList->bind('getTransCoding',function ($url) use ($queryList){\n            return GetTransCoding::getTransCoding($queryList, $url);\n        });\n\n    }\n\n    public static function getTransCoding(QueryList $ql, $url)\n    {\n        $response = wp_remote_get($url, [\n            'timeout' => 10,\n            'user-agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',\n            'user-sslverify' => false,\n        ]);\n        $encode = mb_detect_encoding($response['body'], array(\"ASCII\", \"UTF-8\", \"GB2312\", \"GBK\", \"BIG5\"));\n        $html = iconv($encode, \"utf-8\", $response['body']);\n        $ql->setHtml($html);\n        return $ql;\n    }\n}"
  },
  {
    "path": "vendor/autoload.php",
    "content": "<?php\n\n// autoload.php @generated by Composer\n\nrequire_once __DIR__ . '/composer/autoload_real.php';\n\nreturn ComposerAutoloaderInit15ad0a0b334e2ea46dbbf214582f0b16::getLoader();\n"
  },
  {
    "path": "vendor/cache/adapter-common/AbstractCachePool.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\nuse Cache\\Adapter\\Common\\Exception\\CacheException;\nuse Cache\\Adapter\\Common\\Exception\\CachePoolException;\nuse Cache\\Adapter\\Common\\Exception\\InvalidArgumentException;\nuse Psr\\Cache\\CacheItemInterface;\nuse Psr\\Log\\LoggerAwareInterface;\nuse Psr\\Log\\LoggerInterface;\nuse Psr\\SimpleCache\\CacheInterface;\n\n/**\n * @author Aaron Scherer <aequasi@gmail.com>\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\nabstract class AbstractCachePool implements PhpCachePool, LoggerAwareInterface, CacheInterface\n{\n    const SEPARATOR_TAG = '!';\n\n    /**\n     * @type LoggerInterface\n     */\n    private $logger;\n\n    /**\n     * @type PhpCacheItem[] deferred\n     */\n    protected $deferred = [];\n\n    /**\n     * @param PhpCacheItem $item\n     * @param int|null     $ttl  seconds from now\n     *\n     * @return bool true if saved\n     */\n    abstract protected function storeItemInCache(PhpCacheItem $item, $ttl);\n\n    /**\n     * Fetch an object from the cache implementation.\n     *\n     * If it is a cache miss, it MUST return [false, null, [], null]\n     *\n     * @param string $key\n     *\n     * @return array with [isHit, value, tags[], expirationTimestamp]\n     */\n    abstract protected function fetchObjectFromCache($key);\n\n    /**\n     * Clear all objects from cache.\n     *\n     * @return bool false if error\n     */\n    abstract protected function clearAllObjectsFromCache();\n\n    /**\n     * Remove one object from cache.\n     *\n     * @param string $key\n     *\n     * @return bool\n     */\n    abstract protected function clearOneObjectFromCache($key);\n\n    /**\n     * Get an array with all the values in the list named $name.\n     *\n     * @param string $name\n     *\n     * @return array\n     */\n    abstract protected function getList($name);\n\n    /**\n     * Remove the list.\n     *\n     * @param string $name\n     *\n     * @return bool\n     */\n    abstract protected function removeList($name);\n\n    /**\n     * Add a item key on a list named $name.\n     *\n     * @param string $name\n     * @param string $key\n     */\n    abstract protected function appendListItem($name, $key);\n\n    /**\n     * Remove an item from the list.\n     *\n     * @param string $name\n     * @param string $key\n     */\n    abstract protected function removeListItem($name, $key);\n\n    /**\n     * Make sure to commit before we destruct.\n     */\n    public function __destruct()\n    {\n        $this->commit();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getItem($key)\n    {\n        $this->validateKey($key);\n        if (isset($this->deferred[$key])) {\n            /** @type CacheItem $item */\n            $item = clone $this->deferred[$key];\n            $item->moveTagsToPrevious();\n\n            return $item;\n        }\n\n        $func = function () use ($key) {\n            try {\n                return $this->fetchObjectFromCache($key);\n            } catch (\\Exception $e) {\n                $this->handleException($e, __FUNCTION__);\n            }\n        };\n\n        return new CacheItem($key, $func);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getItems(array $keys = [])\n    {\n        $items = [];\n        foreach ($keys as $key) {\n            $items[$key] = $this->getItem($key);\n        }\n\n        return $items;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function hasItem($key)\n    {\n        try {\n            return $this->getItem($key)->isHit();\n        } catch (\\Exception $e) {\n            $this->handleException($e, __FUNCTION__);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function clear()\n    {\n        // Clear the deferred items\n        $this->deferred = [];\n\n        try {\n            return $this->clearAllObjectsFromCache();\n        } catch (\\Exception $e) {\n            $this->handleException($e, __FUNCTION__);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteItem($key)\n    {\n        try {\n            return $this->deleteItems([$key]);\n        } catch (\\Exception $e) {\n            $this->handleException($e, __FUNCTION__);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteItems(array $keys)\n    {\n        $deleted = true;\n        foreach ($keys as $key) {\n            $this->validateKey($key);\n\n            // Delete form deferred\n            unset($this->deferred[$key]);\n\n            // We have to commit here to be able to remove deferred hierarchy items\n            $this->commit();\n            $this->preRemoveItem($key);\n\n            if (!$this->clearOneObjectFromCache($key)) {\n                $deleted = false;\n            }\n        }\n\n        return $deleted;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function save(CacheItemInterface $item)\n    {\n        if (!$item instanceof PhpCacheItem) {\n            $e = new InvalidArgumentException('Cache items are not transferable between pools. Item MUST implement PhpCacheItem.');\n            $this->handleException($e, __FUNCTION__);\n        }\n\n        $this->removeTagEntries($item);\n        $this->saveTags($item);\n        $timeToLive = null;\n        if (null !== $timestamp = $item->getExpirationTimestamp()) {\n            $timeToLive = $timestamp - time();\n\n            if ($timeToLive < 0) {\n                return $this->deleteItem($item->getKey());\n            }\n        }\n\n        try {\n            return $this->storeItemInCache($item, $timeToLive);\n        } catch (\\Exception $e) {\n            $this->handleException($e, __FUNCTION__);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function saveDeferred(CacheItemInterface $item)\n    {\n        $this->deferred[$item->getKey()] = $item;\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function commit()\n    {\n        $saved = true;\n        foreach ($this->deferred as $item) {\n            if (!$this->save($item)) {\n                $saved = false;\n            }\n        }\n        $this->deferred = [];\n\n        return $saved;\n    }\n\n    /**\n     * @param string $key\n     *\n     * @throws InvalidArgumentException\n     */\n    protected function validateKey($key)\n    {\n        if (!is_string($key)) {\n            $e = new InvalidArgumentException(sprintf(\n                'Cache key must be string, \"%s\" given',\n                gettype($key)\n            ));\n            $this->handleException($e, __FUNCTION__);\n        }\n        if (!isset($key[0])) {\n            $e = new InvalidArgumentException('Cache key cannot be an empty string');\n            $this->handleException($e, __FUNCTION__);\n        }\n        if (preg_match('|[\\{\\}\\(\\)/\\\\\\@\\:]|', $key)) {\n            $e = new InvalidArgumentException(sprintf(\n                'Invalid key: \"%s\". The key contains one or more characters reserved for future extension: {}()/\\@:',\n                $key\n            ));\n            $this->handleException($e, __FUNCTION__);\n        }\n    }\n\n    /**\n     * @param LoggerInterface $logger\n     */\n    public function setLogger(LoggerInterface $logger): void\n    {\n        $this->logger = $logger;\n    }\n\n    /**\n     * Logs with an arbitrary level if the logger exists.\n     *\n     * @param mixed  $level\n     * @param string $message\n     * @param array  $context\n     */\n    protected function log($level, $message, array $context = [])\n    {\n        if ($this->logger !== null) {\n            $this->logger->log($level, $message, $context);\n        }\n    }\n\n    /**\n     * Log exception and rethrow it.\n     *\n     * @param \\Exception $e\n     * @param string     $function\n     *\n     * @throws CachePoolException\n     */\n    private function handleException(\\Exception $e, $function)\n    {\n        $level = 'alert';\n        if ($e instanceof InvalidArgumentException) {\n            $level = 'warning';\n        }\n\n        $this->log($level, $e->getMessage(), ['exception' => $e]);\n        if (!$e instanceof CacheException) {\n            $e = new CachePoolException(sprintf('Exception thrown when executing \"%s\". ', $function), 0, $e);\n        }\n\n        throw $e;\n    }\n\n    /**\n     * @param array $tags\n     *\n     * @return bool\n     */\n    public function invalidateTags(array $tags)\n    {\n        $itemIds = [];\n        foreach ($tags as $tag) {\n            $itemIds = array_merge($itemIds, $this->getList($this->getTagKey($tag)));\n        }\n\n        // Remove all items with the tag\n        $success = $this->deleteItems($itemIds);\n\n        if ($success) {\n            // Remove the tag list\n            foreach ($tags as $tag) {\n                $this->removeList($this->getTagKey($tag));\n                $l = $this->getList($this->getTagKey($tag));\n            }\n        }\n\n        return $success;\n    }\n\n    public function invalidateTag($tag)\n    {\n        return $this->invalidateTags([$tag]);\n    }\n\n    /**\n     * @param PhpCacheItem $item\n     */\n    protected function saveTags(PhpCacheItem $item)\n    {\n        $tags = $item->getTags();\n        foreach ($tags as $tag) {\n            $this->appendListItem($this->getTagKey($tag), $item->getKey());\n        }\n    }\n\n    /**\n     * Removes the key form all tag lists. When an item with tags is removed\n     * we MUST remove the tags. If we fail to remove the tags a new item with\n     * the same key will automatically get the previous tags.\n     *\n     * @param string $key\n     *\n     * @return $this\n     */\n    protected function preRemoveItem($key)\n    {\n        $item = $this->getItem($key);\n        $this->removeTagEntries($item);\n\n        return $this;\n    }\n\n    /**\n     * @param PhpCacheItem $item\n     */\n    private function removeTagEntries(PhpCacheItem $item)\n    {\n        $tags = $item->getPreviousTags();\n        foreach ($tags as $tag) {\n            $this->removeListItem($this->getTagKey($tag), $item->getKey());\n        }\n    }\n\n    /**\n     * @param string $tag\n     *\n     * @return string\n     */\n    protected function getTagKey($tag)\n    {\n        return 'tag'.self::SEPARATOR_TAG.$tag;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function get($key, $default = null)\n    {\n        $item = $this->getItem($key);\n        if (!$item->isHit()) {\n            return $default;\n        }\n\n        return $item->get();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function set($key, $value, $ttl = null)\n    {\n        $item = $this->getItem($key);\n        $item->set($value);\n        $item->expiresAfter($ttl);\n\n        return $this->save($item);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete($key)\n    {\n        return $this->deleteItem($key);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getMultiple($keys, $default = null)\n    {\n        if (!is_array($keys)) {\n            if (!$keys instanceof \\Traversable) {\n                throw new InvalidArgumentException('$keys is neither an array nor Traversable');\n            }\n\n            // Since we need to throw an exception if *any* key is invalid, it doesn't\n            // make sense to wrap iterators or something like that.\n            $keys = iterator_to_array($keys, false);\n        }\n\n        $items = $this->getItems($keys);\n\n        return $this->generateValues($default, $items);\n    }\n\n    /**\n     * @param $default\n     * @param $items\n     *\n     * @return \\Generator\n     */\n    private function generateValues($default, $items)\n    {\n        foreach ($items as $key => $item) {\n            /** @type $item CacheItemInterface */\n            if (!$item->isHit()) {\n                yield $key => $default;\n            } else {\n                yield $key => $item->get();\n            }\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setMultiple($values, $ttl = null)\n    {\n        if (!is_array($values)) {\n            if (!$values instanceof \\Traversable) {\n                throw new InvalidArgumentException('$values is neither an array nor Traversable');\n            }\n        }\n\n        $keys        = [];\n        $arrayValues = [];\n        foreach ($values as $key => $value) {\n            if (is_int($key)) {\n                $key = (string) $key;\n            }\n            $this->validateKey($key);\n            $keys[]            = $key;\n            $arrayValues[$key] = $value;\n        }\n\n        $items       = $this->getItems($keys);\n        $itemSuccess = true;\n        foreach ($items as $key => $item) {\n            $item->set($arrayValues[$key]);\n\n            try {\n                $item->expiresAfter($ttl);\n            } catch (InvalidArgumentException $e) {\n                throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);\n            }\n\n            $itemSuccess = $itemSuccess && $this->saveDeferred($item);\n        }\n\n        return $itemSuccess && $this->commit();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteMultiple($keys)\n    {\n        if (!is_array($keys)) {\n            if (!$keys instanceof \\Traversable) {\n                throw new InvalidArgumentException('$keys is neither an array nor Traversable');\n            }\n\n            // Since we need to throw an exception if *any* key is invalid, it doesn't\n            // make sense to wrap iterators or something like that.\n            $keys = iterator_to_array($keys, false);\n        }\n\n        return $this->deleteItems($keys);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function has($key)\n    {\n        return $this->hasItem($key);\n    }\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/CacheItem.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\nuse Cache\\Adapter\\Common\\Exception\\InvalidArgumentException;\nuse Cache\\TagInterop\\TaggableCacheItemInterface;\n\n/**\n * @author Aaron Scherer <aequasi@gmail.com>\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\nclass CacheItem implements PhpCacheItem\n{\n    /**\n     * @type array\n     */\n    private $prevTags = [];\n\n    /**\n     * @type array\n     */\n    private $tags = [];\n\n    /**\n     * @type \\Closure\n     */\n    private $callable;\n\n    /**\n     * @type string\n     */\n    private $key;\n\n    /**\n     * @type mixed\n     */\n    private $value;\n\n    /**\n     * The expiration timestamp is the source of truth. This is the UTC timestamp\n     * when the cache item expire. A value of zero means it never expires. A nullvalue\n     * means that no expiration is set.\n     *\n     * @type int|null\n     */\n    private $expirationTimestamp = null;\n\n    /**\n     * @type bool\n     */\n    private $hasValue = false;\n\n    /**\n     * @param string        $key\n     * @param \\Closure|bool $callable or boolean hasValue\n     */\n    public function __construct($key, $callable = null, $value = null)\n    {\n        $this->key = $key;\n\n        if ($callable === true) {\n            $this->hasValue = true;\n            $this->value    = $value;\n        } elseif ($callable !== false) {\n            // This must be a callable or null\n            $this->callable = $callable;\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getKey()\n    {\n        return $this->key;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function set($value)\n    {\n        $this->value    = $value;\n        $this->hasValue = true;\n        $this->callable = null;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function get()\n    {\n        if (!$this->isHit()) {\n            return;\n        }\n\n        return $this->value;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function isHit()\n    {\n        $this->initialize();\n\n        if (!$this->hasValue) {\n            return false;\n        }\n\n        if ($this->expirationTimestamp !== null) {\n            return $this->expirationTimestamp > time();\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getExpirationTimestamp()\n    {\n        return $this->expirationTimestamp;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function expiresAt($expiration)\n    {\n        if ($expiration instanceof \\DateTimeInterface) {\n            $this->expirationTimestamp = $expiration->getTimestamp();\n        } elseif (is_int($expiration) || null === $expiration) {\n            $this->expirationTimestamp = $expiration;\n        } else {\n            throw new InvalidArgumentException('Cache item ttl/expiresAt must be of type integer or \\DateTimeInterface.');\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function expiresAfter($time)\n    {\n        if ($time === null) {\n            $this->expirationTimestamp = null;\n        } elseif ($time instanceof \\DateInterval) {\n            $date = new \\DateTime();\n            $date->add($time);\n            $this->expirationTimestamp = $date->getTimestamp();\n        } elseif (is_int($time)) {\n            $this->expirationTimestamp = time() + $time;\n        } else {\n            throw new InvalidArgumentException('Cache item ttl/expiresAfter must be of type integer or \\DateInterval.');\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getPreviousTags()\n    {\n        $this->initialize();\n\n        return $this->prevTags;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getTags()\n    {\n        return $this->tags;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setTags(array $tags)\n    {\n        $this->tags = [];\n        $this->tag($tags);\n\n        return $this;\n    }\n\n    /**\n     * Adds a tag to a cache item.\n     *\n     * @param string|string[] $tags A tag or array of tags\n     *\n     * @throws InvalidArgumentException When $tag is not valid.\n     *\n     * @return TaggableCacheItemInterface\n     */\n    private function tag($tags)\n    {\n        $this->initialize();\n\n        if (!is_array($tags)) {\n            $tags = [$tags];\n        }\n        foreach ($tags as $tag) {\n            if (!is_string($tag)) {\n                throw new InvalidArgumentException(sprintf('Cache tag must be string, \"%s\" given', is_object($tag) ? get_class($tag) : gettype($tag)));\n            }\n            if (isset($this->tags[$tag])) {\n                continue;\n            }\n            if (!isset($tag[0])) {\n                throw new InvalidArgumentException('Cache tag length must be greater than zero');\n            }\n            if (isset($tag[strcspn($tag, '{}()/\\@:')])) {\n                throw new InvalidArgumentException(sprintf('Cache tag \"%s\" contains reserved characters {}()/\\@:', $tag));\n            }\n            $this->tags[$tag] = $tag;\n        }\n\n        return $this;\n    }\n\n    /**\n     * If callable is not null, execute it an populate this object with values.\n     */\n    private function initialize()\n    {\n        if ($this->callable !== null) {\n            // $func will be $adapter->fetchObjectFromCache();\n            $func                      = $this->callable;\n            $result                    = $func();\n            $this->hasValue            = $result[0];\n            $this->value               = $result[1];\n            $this->prevTags            = isset($result[2]) ? $result[2] : [];\n            $this->expirationTimestamp = null;\n\n            if (isset($result[3]) && is_int($result[3])) {\n                $this->expirationTimestamp = $result[3];\n            }\n\n            $this->callable = null;\n        }\n    }\n\n    /**\n     * @internal This function should never be used and considered private.\n     *\n     * Move tags from $tags to $prevTags\n     */\n    public function moveTagsToPrevious()\n    {\n        $this->prevTags = $this->tags;\n        $this->tags     = [];\n    }\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/Changelog.md",
    "content": "# Change Log\n\nThe change log describes what is \"Added\", \"Removed\", \"Changed\" or \"Fixed\" between each release.\n\n## 1.3.0\n\n* Support for PHP 8.1\n* Drop support for PHP < 7.4\n* Allow psr/cache: ^1.0 || ^2.0\n\n## 1.2.0\n\n### Added\n\n* Support for PHP 8\n\n## 1.1.0\n\n### Added\n\n- Support for storing binary data\n\n### Fixed\n\n- Issue with one character variables\n\n### Changed\n\n- Tests are now extending `PHPUnit\\Framework\\TestCase`\n\n## 1.0.0\n\n* No changes since 0.4.0.\n\n## 0.4.0\n\n### Added\n\n* `AbstractCachePool` has 4 new abstract methods: `getList`, `removeList`, `appendListItem` and `removeListItem`.\n* `AbstractCachePool::invalidateTags` and `AbstractCachePool::invalidateTags`\n* Added interfaces for our items and pools `PhpCachePool` and `PhpCacheItem`\n* Trait to help adapters to support tags. `TagSupportWithArray`.\n\n### Changed\n\n* First parameter to `AbstractCachePool::storeItemInCache` must be a `PhpCacheItem`.\n* Return value from `AbstractCachePool::fetchObjectFromCache` must be a an array with 4 values. Added expiration timestamp.\n* `HasExpirationDateInterface` is replaced by `HasExpirationTimestampInterface`\n* We do not work with `\\DateTime` internally anymore. We work with timestamps.\n\n## 0.3.3\n\n### Fixed\n\n* Bugfix when you fetch data from the cache storage that was saved as \"non-tagging item\" but fetch as a tagging item.\n\n## 0.3.2\n\n### Added\n\n* Cache pools do implement `LoggerAwareInterface`\n\n## 0.3.0\n\n### Changed\n\n* The `AbstractCachePool` does not longer implement `TaggablePoolInterface`. However, the `CacheItem` does still implement `TaggableItemInterface`.\n* `CacheItem::getKeyFromTaggedKey` has been removed\n* The `CacheItem`'s second parameter is a callable that must return an array with 3 elements; [`hasValue`, `value`, `tags`].\n\n## 0.2.0\n\n* No changelog before this version\n"
  },
  {
    "path": "vendor/cache/adapter-common/Exception/CacheException.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common\\Exception;\n\nuse Psr\\Cache\\CacheException as CacheExceptionInterface;\n\n/**\n * A base exception. All exceptions in this organization will extend this exception.\n *\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\nabstract class CacheException extends \\RuntimeException implements CacheExceptionInterface\n{\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/Exception/CachePoolException.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common\\Exception;\n\n/**\n * If an exception is caused by a pool or by the cache storage.\n *\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\nclass CachePoolException extends CacheException\n{\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/Exception/InvalidArgumentException.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common\\Exception;\n\nuse Psr\\Cache\\InvalidArgumentException as CacheInvalidArgumentException;\nuse Psr\\SimpleCache\\InvalidArgumentException as SimpleCacheInvalidArgumentException;\n\nclass InvalidArgumentException extends CacheException implements CacheInvalidArgumentException, SimpleCacheInvalidArgumentException\n{\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/HasExpirationTimestampInterface.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\n/**\n * @author Aaron Scherer <aequasi@gmail.com>\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\ninterface HasExpirationTimestampInterface\n{\n    /**\n     * The timestamp when the object expires.\n     *\n     * @return int|null\n     */\n    public function getExpirationTimestamp();\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/JsonBinaryArmoring.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\n/**\n * This trait provides common routines for safely encoding binary and non-UTF8 data in\n * JSON. This is needed for components that use JSON natively (currently, the MongoDB\n * adapter and EncryptedCachePool).\n *\n * @author Stephen Clouse <stephen.clouse@noaa.gov>\n */\ntrait JsonBinaryArmoring\n{\n    private static $ESCAPE_JSON_CHARACTERS = [\n        \"\\x00\", \"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\", \"\\x06\", \"\\x07\",\n        \"\\x08\", \"\\x09\", \"\\x0A\", \"\\x0B\", \"\\x0C\", \"\\x0D\", \"\\x0E\", \"\\x0F\",\n        \"\\x10\", \"\\x11\", \"\\x12\", \"\\x13\", \"\\x14\", \"\\x15\", \"\\x16\", \"\\x17\",\n        \"\\x18\", \"\\x19\", \"\\x1A\", \"\\x1B\", \"\\x1C\", \"\\x1D\", \"\\x1E\", \"\\x1F\",\n    ];\n\n    private static $ENCODED_JSON_CHARACTERS = [\n        '\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', '\\u0005', '\\u0006', '\\u0007',\n        '\\u0008', '\\u0009', '\\u000A', '\\u000B', '\\u000C', '\\u000D', '\\u000E', '\\u000F',\n        '\\u0010', '\\u0011', '\\u0012', '\\u0013', '\\u0014', '\\u0015', '\\u0016', '\\u0017',\n        '\\u0018', '\\u0019', '\\u001A', '\\u001B', '\\u001C', '\\u001D', '\\u001E', '\\u001F',\n    ];\n\n    /**\n     * Armor a value going into a JSON document.\n     *\n     * @param string $value\n     *\n     * @return string\n     */\n    protected static function jsonArmor($value)\n    {\n        return str_replace(\n            static::$ESCAPE_JSON_CHARACTERS,\n            static::$ENCODED_JSON_CHARACTERS,\n            utf8_encode($value)\n        );\n    }\n\n    /**\n     * De-armor a value from a JSON document.\n     *\n     * @param string $value\n     *\n     * @return string\n     */\n    protected static function jsonDeArmor($value)\n    {\n        return utf8_decode(str_replace(\n            static::$ENCODED_JSON_CHARACTERS,\n            static::$ESCAPE_JSON_CHARACTERS,\n            $value\n        ));\n    }\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Aaron Scherer, Tobias Nyholm\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "vendor/cache/adapter-common/PhpCacheItem.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\nuse Cache\\TagInterop\\TaggableCacheItemInterface;\n\n/**\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\ninterface PhpCacheItem extends HasExpirationTimestampInterface, TaggableCacheItemInterface\n{\n    /**\n     * Get the current tags. These are not the same tags as getPrevious tags. This\n     * is the tags that has been added to the item after the item was fetched from\n     * the cache storage.\n     *\n     * WARNING: This is generally not the function you want to use. Please see\n     * `getPreviousTags`.\n     *\n     * @return array\n     */\n    public function getTags();\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/PhpCachePool.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\nuse Cache\\TagInterop\\TaggableCacheItemPoolInterface;\n\n/**\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\ninterface PhpCachePool extends TaggableCacheItemPoolInterface\n{\n    /**\n     * {@inheritdoc}\n     *\n     * @return PhpCacheItem\n     */\n    public function getItem($key);\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return array|\\Traversable|PhpCacheItem[]\n     */\n    public function getItems(array $keys = []);\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/README.md",
    "content": "# Common PSR-6 Cache pool \n[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)\n[![Latest Stable Version](https://poser.pugx.org/cache/adapter-common/v/stable)](https://packagist.org/packages/cache/adapter-common)\n[![codecov.io](https://codecov.io/github/php-cache/adapter-common/coverage.svg?branch=master)](https://codecov.io/github/php-cache/adapter-common?branch=master)\n[![Total Downloads](https://poser.pugx.org/cache/adapter-common/downloads)](https://packagist.org/packages/cache/adapter-common)\n[![Monthly Downloads](https://poser.pugx.org/cache/adapter-common/d/monthly.png)](https://packagist.org/packages/cache/adapter-common)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)\n\nThis repository contains shared classes and interfaces used by the PHP Cache organisation. To read about \nfeatures like tagging and hierarchy support please read the shared documentation at [www.php-cache.com](http://www.php-cache.com). \n\n### Contribute\n\nContributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or \nreport any issues you find on the [issue tracker](http://issues.php-cache.com).\n"
  },
  {
    "path": "vendor/cache/adapter-common/TagSupportWithArray.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Common;\n\n/**\n * This trait could be used by adapters that do not have a native support for lists.\n *\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\ntrait TagSupportWithArray\n{\n    /**\n     * Get a value from the storage.\n     *\n     * @param string $name\n     *\n     * @return mixed\n     */\n    abstract public function getDirectValue($name);\n\n    /**\n     * Set a value to the storage.\n     *\n     * @param string $name\n     * @param mixed  $value\n     */\n    abstract public function setDirectValue($name, $value);\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function appendListItem($name, $value)\n    {\n        $data = $this->getDirectValue($name);\n        if (!is_array($data)) {\n            $data = [];\n        }\n        $data[] = $value;\n        $this->setDirectValue($name, $data);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function getList($name)\n    {\n        $data = $this->getDirectValue($name);\n        if (!is_array($data)) {\n            $data = [];\n        }\n\n        return $data;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function removeList($name)\n    {\n        $this->setDirectValue($name, []);\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function removeListItem($name, $key)\n    {\n        $data = $this->getList($name);\n        foreach ($data as $i => $value) {\n            if ($key === $value) {\n                unset($data[$i]);\n            }\n        }\n\n        return $this->setDirectValue($name, $data);\n    }\n}\n"
  },
  {
    "path": "vendor/cache/adapter-common/composer.json",
    "content": "{\n    \"name\": \"cache/adapter-common\",\n    \"description\": \"Common classes for PSR-6 adapters\",\n    \"license\": \"MIT\",\n    \"type\": \"library\",\n    \"keywords\": [\n        \"cache\",\n        \"psr-6\",\n        \"tag\"\n    ],\n    \"authors\": [\n        {\n            \"name\": \"Aaron Scherer\",\n            \"email\": \"aequasi@gmail.com\",\n            \"homepage\": \"https://github.com/aequasi\"\n        },\n        {\n            \"name\": \"Tobias Nyholm\",\n            \"email\": \"tobias.nyholm@gmail.com\",\n            \"homepage\": \"https://github.com/nyholm\"\n        }\n    ],\n    \"homepage\": \"http://www.php-cache.com/en/latest/\",\n    \"require\": {\n        \"php\": \">=7.4\",\n        \"cache/tag-interop\": \"^1.0\",\n        \"psr/cache\": \"^1.0 || ^2.0\",\n        \"psr/log\": \"^1.0 || ^2.0 || ^3.0\",\n        \"psr/simple-cache\": \"^1.0\"\n    },\n    \"require-dev\": {\n        \"cache/integration-tests\": \"^0.17\",\n        \"phpunit/phpunit\": \"^7.5.20 || ^9.5.10\"\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true,\n    \"autoload\": {\n        \"psr-4\": {\n            \"Cache\\\\Adapter\\\\Common\\\\\": \"\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Cache\\\\Adapter\\\\Common\\\\Tests\\\\\": \"Tests/\"\n        },\n        \"exclude-from-classmap\": [\n            \"/Tests/\"\n        ]\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.1-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/cache/filesystem-adapter/Changelog.md",
    "content": "# Change Log\n\nThe change log describes what is \"Added\", \"Removed\", \"Changed\" or \"Fixed\" between each release.\n\n## UNRELEASED\n\n## 1.2.0\n\n* Support for PHP 8.1\n* Drop support for PHP < 7.4\n* Allow psr/cache: ^1.0 || ^2.0\n\n## 1.1.0\n\n### Added\n\n* Support for PHP 8\n\n### Changed\n\n* Use `League\\Flysystem\\FilesystemInterface` instead of concrete `League\\Flysystem\\Filesystem` class\n\n## 1.0.0\n\n* No changes since 0.4.0\n\n## 0.4.0\n\n### Added\n\n* Support for the new `TaggableCacheItemPoolInterface`.\n* Support for PSR-16 SimpleCache\n\n### Changed\n\n* The behavior of `CacheItem::getTags()` has changed. It will not return the tags stored in the cache storage.\n\n### Removed\n\n* `CacheItem::getExpirationDate()`. Use `CacheItem::getExpirationTimestamp()`\n* `CacheItem::getTags()`. Use `CacheItem::getPreviousTags()`\n* `CacheItem::addTag()`. Use `CacheItem::setTags()`\n\n## 0.3.3\n\n### Fixed\n\n* Race condition in `fetchObjectFromCache`.\n\n## 0.3.2\n\n### Changed\n\n* Using `Filesystem::update` instead of `Filesystem::delete` and `Filesystem::write`.\n\n## 0.3.1\n\n### Added\n\n* Add ability to change cache path in FilesystemCachePool\n\n## 0.3.0\n\n* No changelog before this version\n"
  },
  {
    "path": "vendor/cache/filesystem-adapter/FilesystemCachePool.php",
    "content": "<?php\n\n/*\n * This file is part of php-cache organization.\n *\n * (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>\n *\n * This source file is subject to the MIT license that is bundled\n * with this source code in the file LICENSE.\n */\n\nnamespace Cache\\Adapter\\Filesystem;\n\nuse Cache\\Adapter\\Common\\AbstractCachePool;\nuse Cache\\Adapter\\Common\\Exception\\InvalidArgumentException;\nuse Cache\\Adapter\\Common\\PhpCacheItem;\nuse League\\Flysystem\\FileExistsException;\nuse League\\Flysystem\\FileNotFoundException;\nuse League\\Flysystem\\FilesystemInterface;\n\n/**\n * @author Tobias Nyholm <tobias.nyholm@gmail.com>\n */\nclass FilesystemCachePool extends AbstractCachePool\n{\n    /**\n     * @type FilesystemInterface\n     */\n    private $filesystem;\n\n    /**\n     * The folder should not begin nor end with a slash. Example: path/to/cache.\n     *\n     * @type string\n     */\n    private $folder;\n\n    /**\n     * @param FilesystemInterface $filesystem\n     * @param string              $folder\n     */\n    public function __construct(FilesystemInterface $filesystem, $folder = 'cache')\n    {\n        $this->folder = $folder;\n\n        $this->filesystem = $filesystem;\n        $this->filesystem->createDir($this->folder);\n    }\n\n    /**\n     * @param string $folder\n     */\n    public function setFolder($folder)\n    {\n        $this->folder = $folder;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function fetchObjectFromCache($key)\n    {\n        $empty = [false, null, [], null];\n        $file  = $this->getFilePath($key);\n\n        try {\n            $data = @unserialize($this->filesystem->read($file));\n            if ($data === false) {\n                return $empty;\n            }\n        } catch (FileNotFoundException $e) {\n            return $empty;\n        }\n\n        // Determine expirationTimestamp from data, remove items if expired\n        $expirationTimestamp = $data[2] ?: null;\n        if ($expirationTimestamp !== null && time() > $expirationTimestamp) {\n            foreach ($data[1] as $tag) {\n                $this->removeListItem($this->getTagKey($tag), $key);\n            }\n            $this->forceClear($key);\n\n            return $empty;\n        }\n\n        return [true, $data[0], $data[1], $expirationTimestamp];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function clearAllObjectsFromCache()\n    {\n        $this->filesystem->deleteDir($this->folder);\n        $this->filesystem->createDir($this->folder);\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function clearOneObjectFromCache($key)\n    {\n        return $this->forceClear($key);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function storeItemInCache(PhpCacheItem $item, $ttl)\n    {\n        $data = serialize(\n            [\n                $item->get(),\n                $item->getTags(),\n                $item->getExpirationTimestamp(),\n            ]\n        );\n\n        $file = $this->getFilePath($item->getKey());\n        if ($this->filesystem->has($file)) {\n            // Update file if it exists\n            return $this->filesystem->update($file, $data);\n        }\n\n        try {\n            return $this->filesystem->write($file, $data);\n        } catch (FileExistsException $e) {\n            // To handle issues when/if race conditions occurs, we try to update here.\n            return $this->filesystem->update($file, $data);\n        }\n    }\n\n    /**\n     * @param string $key\n     *\n     * @throws InvalidArgumentException\n     *\n     * @return string\n     */\n    private function getFilePath($key)\n    {\n        if (!preg_match('|^[a-zA-Z0-9_\\.! ]+$|', $key)) {\n            throw new InvalidArgumentException(sprintf('Invalid key \"%s\". Valid filenames must match [a-zA-Z0-9_\\.! ].', $key));\n        }\n\n        return sprintf('%s/%s', $this->folder, $key);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function getList($name)\n    {\n        $file = $this->getFilePath($name);\n\n        if (!$this->filesystem->has($file)) {\n            $this->filesystem->write($file, serialize([]));\n        }\n\n        return unserialize($this->filesystem->read($file));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function removeList($name)\n    {\n        $file = $this->getFilePath($name);\n        $this->filesystem->delete($file);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function appendListItem($name, $key)\n    {\n        $list   = $this->getList($name);\n        $list[] = $key;\n\n        return $this->filesystem->update($this->getFilePath($name), serialize($list));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function removeListItem($name, $key)\n    {\n        $list = $this->getList($name);\n        foreach ($list as $i => $item) {\n            if ($item === $key) {\n                unset($list[$i]);\n            }\n        }\n\n        return $this->filesystem->update($this->getFilePath($name), serialize($list));\n    }\n\n    /**\n     * @param $key\n     *\n     * @return bool\n     */\n    private function forceClear($key)\n    {\n        try {\n            return $this->filesystem->delete($this->getFilePath($key));\n        } catch (FileNotFoundException $e) {\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/cache/filesystem-adapter/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Aaron Scherer, Tobias Nyholm\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "vendor/cache/filesystem-adapter/README.md",
    "content": "# Filesystem PSR-6 Cache pool \n[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)\n[![Latest Stable Version](https://poser.pugx.org/cache/filesystem-adapter/v/stable)](https://packagist.org/packages/cache/filesystem-adapter)\n[![codecov.io](https://codecov.io/github/php-cache/filesystem-adapter/coverage.svg?branch=master)](https://codecov.io/github/php-cache/filesystem-adapter?branch=master)\n[![Total Downloads](https://poser.pugx.org/cache/filesystem-adapter/downloads)](https://packagist.org/packages/cache/filesystem-adapter)\n[![Monthly Downloads](https://poser.pugx.org/cache/filesystem-adapter/d/monthly.png)](https://packagist.org/packages/cache/filesystem-adapter)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)\n\nThis is a PSR-6 cache implementation using Filesystem. It is a part of the PHP Cache organisation. To read about \nfeatures like tagging and hierarchy support please read the shared documentation at [www.php-cache.com](http://www.php-cache.com). \n\nThis implementation is using the excellent [Flysystem](http://flysystem.thephpleague.com/).\n\n### Install\n\n```bash\ncomposer require cache/filesystem-adapter\n```\n\n### Use\n\nTo create an instance of `FilesystemCachePool` you need to configure a `Filesystem` and its adapter. \n\n```php\nuse League\\Flysystem\\Adapter\\Local;\nuse League\\Flysystem\\Filesystem;\nuse Cache\\Adapter\\Filesystem\\FilesystemCachePool;\n\n$filesystemAdapter = new Local(__DIR__.'/');\n$filesystem        = new Filesystem($filesystemAdapter);\n\n$pool = new FilesystemCachePool($filesystem);\n```\n\nYou can change the folder the cache pool will write to through the `setFolder` setter:\n\n```php\n$pool = new FilesystemCachePool($filesystem);\n$pool->setFolder('path/to/cache');\n```\n\n### Contribute\n\nContributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or \nreport any issues you find on the [issue tracker](http://issues.php-cache.com).\n"
  },
  {
    "path": "vendor/cache/filesystem-adapter/composer.json",
    "content": "{\n    \"name\": \"cache/filesystem-adapter\",\n    \"description\": \"A PSR-6 cache implementation using filesystem. This implementation supports tags\",\n    \"license\": \"MIT\",\n    \"type\": \"library\",\n    \"keywords\": [\n        \"cache\",\n        \"psr-6\",\n        \"filesystem\",\n        \"tag\"\n    ],\n    \"authors\": [\n        {\n            \"name\": \"Aaron Scherer\",\n            \"email\": \"aequasi@gmail.com\",\n            \"homepage\": \"https://github.com/aequasi\"\n        },\n        {\n            \"name\": \"Tobias Nyholm\",\n            \"email\": \"tobias.nyholm@gmail.com\",\n            \"homepage\": \"https://github.com/nyholm\"\n        }\n    ],\n    \"homepage\": \"http://www.php-cache.com/en/latest/\",\n    \"require\": {\n        \"php\": \">=7.4\",\n        \"cache/adapter-common\": \"^1.0\",\n        \"league/flysystem\": \"^1.0\",\n        \"psr/cache\": \"^1.0 || ^2.0\",\n        \"psr/simple-cache\": \"^1.0\"\n    },\n    \"require-dev\": {\n        \"cache/integration-tests\": \"^0.17\",\n        \"phpunit/phpunit\": \"^7.5.20 || ^9.5.10\"\n    },\n    \"provide\": {\n        \"psr/cache-implementation\": \"^1.0\",\n        \"psr/simple-cache-implementation\": \"^1.0\"\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true,\n    \"autoload\": {\n        \"psr-4\": {\n            \"Cache\\\\Adapter\\\\Filesystem\\\\\": \"\"\n        },\n        \"exclude-from-classmap\": [\n            \"/Tests/\"\n        ]\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.1-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/clue/socket-raw/.github/FUNDING.yml",
    "content": "github: clue\ncustom: https://clue.engineering/support\n"
  },
  {
    "path": "vendor/clue/socket-raw/.github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n  pull_request:\n\njobs:\n  PHPUnit:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os:\n          - ubuntu-latest\n          - windows-latest\n        php:\n          - 8.0\n          - 7.4\n          - 7.3\n          - 7.2\n          - 7.1\n          - 7.0\n          - 5.6\n          - 5.5\n          - 5.4\n          - 5.3\n    steps:\n      - uses: actions/checkout@v2\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: ${{ matrix.php }}\n          extensions: sockets\n      - run: composer install\n      - run: vendor/bin/phpunit --coverage-text\n        if: ${{ matrix.php >= 7.3 }}\n      - run: vendor/bin/phpunit --coverage-text -c phpunit.xml.legacy\n        if: ${{ matrix.php < 7.3 }}\n"
  },
  {
    "path": "vendor/clue/socket-raw/CHANGELOG.md",
    "content": "# Changelog\n\n## 1.5.0 (2020-11-27)\n\n*   Feature: Support PHP 8 and drop legacy HHVM support.\n    (#60 and #61 by @clue)\n    \n*   Improve test suite and add `.gitattributes` to exclude dev files from export.\n    Update to PHPUnit 9 and simplify test matrix.\n    (#50, #51, #58 and #63 by @clue and #57 by @SimonFrings)\n\n## 1.4.1 (2019-10-28)\n\n*   Fix: Fix error reporting when invoking methods on closed socket instance.\n    (#48 by @clue)\n\n*   Improve test suite to run tests on Windows via Travis CI.\n    (#49 by @clue)\n\n## 1.4.0 (2019-01-22)\n\n*   Feature: Improve Windows support (async connections and Unix domain sockets).\n    (#43 by @clue)\n\n*   Improve test suite by adding forward compatibility with PHPUnit 7 and PHPUnit 6.\n    (#42 by @clue)\n\n## 1.3.0 (2018-06-10)\n\n*   Feature: Add `$timeout` parameter for `Factory::createClient()`\n    (#39 by @Elbandi and @clue)\n\n    ```php\n    // connect to Google, but wait no longer than 2.5s for connection\n    $socket = $factory->createClient('www.google.com:80', 2.5);\n    ```\n\n*   Improve test suite by adding PHPUnit to require-dev,\n    update test suite to test against legacy PHP 5.3 through PHP 7.2 and\n    optionally skip functional integration tests requiring internet.\n    (#26 by @ascii-soup, #28, #29, #37 and #38 by @clue)\n\n## 1.2.0 (2015-03-18)\n\n* Feature: Expose optional `$type` parameter for `Socket::read()`\n  ([#16](https://github.com/clue/php-socket-raw/pull/16) by @Elbandi)\n\n## 1.1.0 (2014-10-24)\n\n* Feature: Accept float timeouts like `0.5` for `Socket::selectRead()` and `Socket::selectWrite()`.\n  ([#8](https://github.com/clue/php-socket-raw/issues/8))\n\n* Feature: Add new `Socket::connectTimeout()` method.\n  ([#11](https://github.com/clue/php-socket-raw/pull/11))\n\n* Fix: Close invalid socket resource when `Factory` fails to create a `Socket`.\n  ([#12](https://github.com/clue/php-socket-raw/pull/12))\n\n* Fix: Calling `accept()` on an idle server socket emits right error code and message.\n  ([#14](https://github.com/clue/php-socket-raw/pull/14))\n\n## 1.0.0 (2014-05-10)\n\n* Feature: Improved errors reporting through dedicated `Exception`\n  ([#6](https://github.com/clue/socket-raw/pull/6))\n* Feature: Support HHVM\n  ([#5](https://github.com/clue/socket-raw/pull/5))\n* Use PSR-4 layout\n  ([#3](https://github.com/clue/socket-raw/pull/3))\n* Continuous integration via Travis CI\n\n## 0.1.2 (2013-05-09)\n\n* Fix: The `Factory::createUdg()` now returns the right socket type.\n* Fix: Fix ICMPv6 addressing to not require square brackets because it does not\n  use ports.\n* Extended test suite.\n\n## 0.1.1 (2013-04-18)\n\n* Fix: Raw sockets now correctly report no port instead of a `0` port.\n\n## 0.1.0 (2013-04-10)\n\n* First tagged release\n"
  },
  {
    "path": "vendor/clue/socket-raw/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013 Christian Lück\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/clue/socket-raw/README.md",
    "content": "# clue/socket-raw\n\n[![CI status](https://github.com/clue/php-socket-raw/workflows/CI/badge.svg)](https://github.com/clue/php-socket-raw/actions)\n\nSimple and lightweight OOP wrapper for PHP's low-level sockets extension (ext-sockets).\n\nPHP offers two networking APIs, the newer [streams API](https://www.php.net/manual/en/book.stream.php) and the older [socket API](https://www.php.net/manual/en/ref.sockets.php).\nWhile the former has been a huge step forward in generalizing various streaming resources,\nit lacks some of the advanced features of the original and much more low-level socket API.\nThis lightweight library exposes this socket API in a modern way by providing a thin wrapper around the underlying API.\n\n* **Full socket API** -\n  It exposes the whole [socket API](https://www.php.net/manual/en/ref.sockets.php) through a *sane* object-oriented interface.\n  Provides convenience methods for common operations as well as exposing all underlying methods and options.\n* **Fluent interface** -\n  Uses a fluent interface so you can easily chain method calls.\n  Error conditions will be signalled using `Exception`s instead of relying on cumbersome return codes.\n* **Lightweight, SOLID design** -\n  Provides a thin abstraction that is [*just good enough*](https://en.wikipedia.org/wiki/Principle_of_good_enough)\n  and does not get in your way.\n  This library is merely a very thin wrapper and has no other external dependencies.\n* **Good test coverage** -\n  Comes with an automated test suite and is regularly tested in the *real world*.\n\n**Table of contents**\n\n* [Support us](#support-us)\n* [Quickstart example](#quickstart-example)\n* [Usage](#usage)\n  * [Factory](#factory)\n    * [createClient()](#createclient)\n    * [createServer()](#createserver)\n    * [create*()](#create)\n  * [Socket](#socket)\n    * [Methods](#methods)\n      * [Data I/O](#data-io)\n      * [Unconnected I/O](#unconnected-io)\n      * [Non-blocking (async) I/O](#non-blocking-async-io)\n      * [Connection handling](#connection-handling)\n* [Install](#install)\n* [Tests](#tests)\n* [License](#license)\n\n## Support us\n\nWe invest a lot of time developing, maintaining and updating our awesome\nopen-source projects. You can help us sustain this high-quality of our work by\n[becoming a sponsor on GitHub](https://github.com/sponsors/clue). Sponsors get\nnumerous benefits in return, see our [sponsoring page](https://github.com/sponsors/clue)\nfor details.\n\nLet's take these projects to the next level together! 🚀\n\n## Quickstart example\n\nOnce [installed](#install), you can use the following example to send and receive HTTP messages:\n\n```php\n$factory = new \\Socket\\Raw\\Factory();\n\n$socket = $factory->createClient('www.google.com:80');\necho 'Connected to ' . $socket->getPeerName() . PHP_EOL;\n\n// send simple HTTP request to remote side\n$socket->write(\"GET / HTTP/1.1\\r\\n\\Host: www.google.com\\r\\n\\r\\n\");\n\n// receive and dump HTTP response\nvar_dump($socket->read(8192));\n\n$socket->close();\n```\n\nSee also the [examples](examples).\n\n## Usage\n\n### Factory\n\nAs shown in the [quickstart example](#quickstart-example), this library uses a `Factory` pattern\nas a simple API to [`socket_create()`](https://www.php.net/manual/en/function.socket-create.php).\nIt provides simple access to creating TCP, UDP, UNIX, UDG and ICMP protocol sockets and supports both IPv4 and IPv6 addressing.\n\n```php\n$factory = new \\Socket\\Raw\\Factory();\n```\n\n#### createClient()\n\nThe `createClient(string $address, null|float $timeout): Socket` method is\nthe most convenient method for creating connected client sockets\n(similar to how [`fsockopen()`](https://www.php.net/manual/en/function.fsockopen.php) or\n[`stream_socket_client()`](https://www.php.net/manual/en/function.stream-socket-client.php) work).\n\n```php\n// establish a TCP/IP stream connection socket to www.google.com on port 80\n$socket = $factory->createClient('tcp://www.google.com:80');\n\n// same as above, as scheme defaults to TCP\n$socket = $factory->createClient('www.google.com:80');\n\n// same as above, but wait no longer than 2.5s for connection\n$socket = $factory->createClient('www.google.com:80', 2.5);\n\n// create connectionless UDP/IP datagram socket connected to google's DNS\n$socket = $factory->createClient('udp://8.8.8.8:53');\n\n// establish TCP/IPv6 stream connection socket to localhost on port 1337\n$socket = $factory->createClient('tcp://[::1]:1337');\n\n// connect to local Unix stream socket path\n$socket = $factory->createClient('unix:///tmp/daemon.sock');\n\n// create Unix datagram socket\n$socket = $factory->createClient('udg:///tmp/udg.socket');\n\n// create a raw low-level ICMP socket (requires root!)\n$socket = $factory->createClient('icmp://192.168.0.1');\n```\n\n#### createServer()\n\nThe `createServer($address)` method can be used to create a server side (listening) socket bound to specific address/path\n(similar to how [`stream_socket_server()`](https://www.php.net/manual/en/function.stream-socket-server.php) works).\nIt accepts the same addressing scheme as the [`createClient()`](#createclient) method.\n\n```php\n// create a TCP/IP stream connection socket server on port 1337\n$socket = $factory->createServer('tcp://localhost:1337');\n\n// create a UDP/IPv6 datagram socket server on port 1337\n$socket = $factory->createServer('udp://[::1]:1337');\n```\n\n#### create*()\n\nLess commonly used, the `Factory` provides access to creating (unconnected) sockets for various socket types:\n\n```php\n$socket = $factory->createTcp4();\n$socket = $factory->createTcp6();\n\n$socket = $factory->createUdp4();\n$socket = $factory->createUdp6();\n\n$socket = $factory->createUnix();\n$socket = $factory->createUdg();\n\n$socket = $factory->createIcmp4();\n$socket = $factory->createIcmp6();\n```\n\nYou can also create arbitrary socket protocol types through the underlying mechanism:\n\n```php\n$factory->create($family, $type, $protocol);\n```\n\n### Socket\n\nAs discussed above, the `Socket` class is merely an object-oriented wrapper around a socket resource. As such, it helps if you're familar with socket programming in general.\n\nThe recommended way to create a `Socket` instance is via the above [`Factory`](#factory).\n\n#### Methods\n\nAll low-level socket operations are available as methods on the `Socket` class.\n\nYou can refer to PHP's fairly good [socket API documentation](https://www.php.net/manual/en/ref.sockets.php) or the docblock comments in the [`Socket` class](src/Socket.php) to get you started.\n\n##### Data I/O:\n\n```\n$socket->write('data');\n$data = $socket->read(8192);\n```\n\n##### Unconnected I/O:\n\n```\n$socket->sendTo('data', $flags, $remote);\n$data = $socket->rcvFrom(8192, $flags, $remote);\n```\n\n##### Non-blocking (async) I/O:\n\n```\n$socket->setBlocking(false);\n$socket->selectRead();\n$socket->selectWrite();\n```\n\n##### Connection handling:\n\n```php\n$client = $socket->accept();\n$socket->bind($address);\n$socket->connect($address);\n$socket->shutdown();\n$socket->close();\n```\n\n## Install\n\nThe recommended way to install this library is [through Composer](https://getcomposer.org).\n[New to Composer?](https://getcomposer.org/doc/00-intro.md)\n\nThis project follows [SemVer](https://semver.org/).\nThis will install the latest supported version:\n\n```bash\n$ composer require clue/socket-raw:^1.5\n```\n\nSee also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.\n\nThis project aims to run on any platform and thus does not require any PHP\nextensions besides `ext-sockets` and supports running on legacy PHP 5.3 through\ncurrent PHP 8+.\nIt's *highly recommended to use PHP 7+* for this project.\n\n## Tests\n\nTo run the test suite, you first need to clone this repo and then install all\ndependencies [through Composer](https://getcomposer.org):\n\n```bash\n$ composer install\n```\n\nTo run the test suite, go to the project root and run:\n\n```bash\n$ php vendor/bin/phpunit\n```\n\nNote that the test suite contains tests for ICMP sockets which require root\naccess on Unix/Linux systems. Therefor some tests will be skipped unless you run\nthe following command to execute the full test suite:\n\n```bash\n$ sudo php vendor/bin/phpunit\n```\n\nThe test suite also contains a number of functional integration tests that rely\non a stable internet connection.\nIf you do not want to run these, they can simply be skipped like this:\n\n```bash\n$ php vendor/bin/phpunit --exclude-group internet\n```\n\n## License\n\nThis project is released under the permissive [MIT license](LICENSE).\n\n> Did you know that I offer custom development services and issuing invoices for\n  sponsorships of releases and for contributions? Contact me (@clue) for details.\n"
  },
  {
    "path": "vendor/clue/socket-raw/composer.json",
    "content": "{\n    \"name\": \"clue/socket-raw\",\n    \"description\": \"Simple and lightweight OOP wrapper for PHP's low-level sockets extension (ext-sockets).\",\n    \"keywords\": [\"socket\", \"stream\", \"datagram\", \"dgram\", \"client\", \"server\", \"ipv6\", \"tcp\", \"udp\", \"icmp\", \"unix\", \"udg\"],\n    \"homepage\": \"https://github.com/clue/php-socket-raw\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Christian Lück\",\n            \"email\": \"christian@clue.engineering\"\n        }\n    ],\n    \"autoload\": {\n        \"psr-4\": {\"Socket\\\\Raw\\\\\": \"src\"}\n    },\n    \"require\": {\n        \"ext-sockets\": \"*\",\n        \"php\": \">=5.3\"\n    },\n    \"require-dev\": {\n        \"phpunit/phpunit\": \"^9.3 || ^5.7 || ^4.8.35\"\n    }\n}\n"
  },
  {
    "path": "vendor/clue/socket-raw/src/Exception.php",
    "content": "<?php\n\nnamespace Socket\\Raw;\n\nuse RuntimeException;\n\nclass Exception extends RuntimeException\n{\n    /**\n     * Create an Exception after a socket operation on the given $resource failed\n     *\n     * @param \\Socket|resource $resource\n     * @param string   $messagePrefix\n     * @return self\n     * @uses socket_last_error() to get last socket error code\n     * @uses socket_clear_error() to clear socket error code\n     * @uses self::createFromCode() to automatically construct exception with full error message\n     */\n    public static function createFromSocketResource($resource, $messagePrefix = 'Socket operation failed')\n    {\n        if (PHP_VERSION_ID >= 80000) {\n            try {\n                $code = socket_last_error($resource);\n            } catch (\\Error $e) {\n                $code = SOCKET_ENOTSOCK;\n            }\n        } elseif (is_resource($resource)) {\n            $code = socket_last_error($resource);\n            socket_clear_error($resource);\n        } else {\n            // socket already closed, return fixed error code instead of operating on invalid handle\n            $code = SOCKET_ENOTSOCK;\n        }\n\n        return self::createFromCode($code, $messagePrefix);\n    }\n\n    /**\n     * Create an Exception after a global socket operation failed (like socket creation)\n     *\n     * @param string $messagePrefix\n     * @return self\n     * @uses socket_last_error() to get last global error code\n     * @uses socket_clear_error() to clear global error code\n     * @uses self::createFromCode() to automatically construct exception with full error message\n     */\n    public static function createFromGlobalSocketOperation($messagePrefix = 'Socket operation failed')\n    {\n        $code = socket_last_error();\n        socket_clear_error();\n\n        return self::createFromCode($code, $messagePrefix);\n    }\n\n    /**\n     * Create an Exception for given error $code\n     *\n     * @param int    $code\n     * @param string $messagePrefix\n     * @return self\n     * @throws Exception if given $val is boolean false\n     * @uses self::getErrorMessage() to translate error code to error message\n     */\n    public static function createFromCode($code, $messagePrefix = 'Socket error')\n    {\n        return new self($messagePrefix . ': ' . self::getErrorMessage($code), $code);\n    }\n\n    /**\n     * get error message for given error code\n     *\n     * @param int $code error code\n     * @return string\n     * @uses socket_strerror() to translate error code to error message\n     * @uses get_defined_constants() to check for related error constant\n     */\n    protected static function getErrorMessage($code)\n    {\n        $string = socket_strerror($code);\n\n        // search constant starting with SOCKET_ for this error code\n        foreach (get_defined_constants() as $key => $value) {\n            if($value === $code && strpos($key, 'SOCKET_') === 0) {\n                $string .= ' (' . $key . ')';\n                break;\n            }\n        }\n\n        return $string;\n    }\n}\n"
  },
  {
    "path": "vendor/clue/socket-raw/src/Factory.php",
    "content": "<?php\n\nnamespace Socket\\Raw;\n\nuse \\InvalidArgumentException;\n\nclass Factory\n{\n    /**\n     * create client socket connected to given target address\n     *\n     * @param string     $address target address to connect to\n     * @param null|float $timeout connection timeout (in seconds), default null = no limit\n     * @return \\Socket\\Raw\\Socket\n     * @throws InvalidArgumentException if given address is invalid\n     * @throws Exception on error\n     * @uses self::createFromString()\n     * @uses Socket::connect()\n     * @uses Socket::connectTimeout()\n     */\n    public function createClient($address, $timeout = null)\n    {\n        $socket = $this->createFromString($address, $scheme);\n\n        try {\n            if ($timeout === null) {\n                $socket->connect($address);\n            } else {\n                // connectTimeout enables non-blocking mode, so turn blocking on again\n                $socket->connectTimeout($address, $timeout);\n                $socket->setBlocking(true);\n            }\n        } catch (Exception $e) {\n            $socket->close();\n            throw $e;\n        }\n\n        return $socket;\n    }\n\n    /**\n     * create server socket bound to given address (and start listening for streaming clients to connect to this stream socket)\n     *\n     * @param string $address address to bind socket to\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::createFromString()\n     * @uses Socket::bind()\n     * @uses Socket::listen() only for stream sockets (TCP/UNIX)\n     */\n    public function createServer($address)\n    {\n        $socket = $this->createFromString($address, $scheme);\n\n        try {\n            $socket->bind($address);\n\n            if ($socket->getType() === SOCK_STREAM) {\n                $socket->listen();\n            }\n        } catch (Exception $e) {\n            $socket->close();\n            throw $e;\n        }\n\n        return $socket;\n    }\n\n    /**\n     * create TCP/IPv4 stream socket\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createTcp4()\n    {\n        return $this->create(AF_INET, SOCK_STREAM, SOL_TCP);\n    }\n\n    /**\n     * create TCP/IPv6 stream socket\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createTcp6()\n    {\n        return $this->create(AF_INET6, SOCK_STREAM, SOL_TCP);\n    }\n\n    /**\n     * create UDP/IPv4 datagram socket\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createUdp4()\n    {\n        return $this->create(AF_INET, SOCK_DGRAM, SOL_UDP);\n    }\n\n    /**\n     * create UDP/IPv6 datagram socket\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createUdp6()\n    {\n        return $this->create(AF_INET6, SOCK_DGRAM, SOL_UDP);\n    }\n\n    /**\n     * create local UNIX stream socket\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createUnix()\n    {\n        return $this->create(AF_UNIX, SOCK_STREAM, 0);\n    }\n\n    /**\n     * create local UNIX datagram socket (UDG)\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createUdg()\n    {\n        return $this->create(AF_UNIX, SOCK_DGRAM, 0);\n    }\n\n    /**\n     * create raw ICMP/IPv4 datagram socket (requires root!)\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createIcmp4()\n    {\n        return $this->create(AF_INET, SOCK_RAW, getprotobyname('icmp'));\n    }\n\n    /**\n     * create raw ICMPv6 (IPv6) datagram socket (requires root!)\n     *\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception on error\n     * @uses self::create()\n     */\n    public function createIcmp6()\n    {\n        return $this->create(AF_INET6, SOCK_RAW, 58 /*getprotobyname('icmp')*/);\n    }\n\n    /**\n     * create low level socket with given arguments\n     *\n     * @param int $domain\n     * @param int $type\n     * @param int $protocol\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception if creating socket fails\n     * @throws \\Error PHP 8 only: throws \\Error when arguments are invalid\n     * @uses socket_create()\n     */\n    public function create($domain, $type, $protocol)\n    {\n        $sock = @socket_create($domain, $type, $protocol);\n        if ($sock === false) {\n            throw Exception::createFromGlobalSocketOperation('Unable to create socket');\n        }\n        return new Socket($sock);\n    }\n\n    /**\n     * create a pair of indistinguishable sockets (commonly used in IPC)\n     *\n     * @param int $domain\n     * @param int $type\n     * @param int $protocol\n     * @return \\Socket\\Raw\\Socket[]\n     * @throws Exception if creating pair of sockets fails\n     * @throws \\Error PHP 8 only: throws \\Error when arguments are invalid\n     * @uses socket_create_pair()\n     */\n    public function createPair($domain, $type, $protocol)\n    {\n        $ret = @socket_create_pair($domain, $type, $protocol, $pair);\n        if ($ret === false) {\n            throw Exception::createFromGlobalSocketOperation('Unable to create pair of sockets');\n        }\n        return array(new Socket($pair[0]), new Socket($pair[1]));\n    }\n\n    /**\n     * create TCP/IPv4 stream socket and listen for new connections\n     *\n     * @param int $port\n     * @param int $backlog\n     * @return \\Socket\\Raw\\Socket\n     * @throws Exception if creating listening socket fails\n     * @throws \\Error PHP 8 only: throws \\Error when arguments are invalid\n     * @uses socket_create_listen()\n     * @see self::createServer() as an alternative to bind to specific IP, IPv6, UDP, UNIX, UGP\n     */\n    public function createListen($port, $backlog = 128)\n    {\n        $sock = @socket_create_listen($port, $backlog);\n        if ($sock === false) {\n            throw Exception::createFromGlobalSocketOperation('Unable to create listening socket');\n        }\n        return new Socket($sock);\n    }\n\n    /**\n     * create socket for given address\n     *\n     * @param string $address (passed by reference in order to remove scheme, if present)\n     * @param string $scheme  default scheme to use, defaults to TCP (passed by reference in order to update with actual scheme used)\n     * @return \\Socket\\Raw\\Socket\n     * @throws InvalidArgumentException if given address is invalid\n     * @throws Exception in case creating socket failed\n     * @uses self::createTcp4() etc.\n     */\n    public function createFromString(&$address, &$scheme)\n    {\n        if ($scheme === null) {\n            $scheme = 'tcp';\n        }\n\n        $hasScheme = false;\n\n        $pos = strpos($address, '://');\n        if ($pos !== false) {\n            $scheme = substr($address, 0, $pos);\n            $address = substr($address, $pos + 3);\n            $hasScheme = true;\n        }\n\n        if (strpos($address, ':') !== strrpos($address, ':') && in_array($scheme, array('tcp', 'udp', 'icmp'))) {\n            // TCP/UDP/ICMP address with several colons => must be IPv6\n            $scheme .= '6';\n        }\n\n        if ($scheme === 'tcp') {\n            $socket = $this->createTcp4();\n        } elseif ($scheme === 'udp') {\n            $socket = $this->createUdp4();\n        } elseif ($scheme === 'tcp6') {\n            $socket = $this->createTcp6();\n        } elseif ($scheme === 'udp6') {\n            $socket = $this->createUdp6();\n        } elseif ($scheme === 'unix') {\n            $socket = $this->createUnix();\n        } elseif ($scheme === 'udg') {\n            $socket = $this->createUdg();\n        } elseif ($scheme === 'icmp') {\n            $socket = $this->createIcmp4();\n        } elseif ($scheme === 'icmp6') {\n            $socket = $this->createIcmp6();\n            if ($hasScheme) {\n                // scheme was stripped from address, resulting IPv6 must not\n                // have a port (due to ICMP) and thus must not be enclosed in\n                // square brackets\n                $address = trim($address, '[]');\n            }\n        } else {\n            throw new InvalidArgumentException('Invalid address scheme given');\n        }\n        return $socket;\n    }\n}\n"
  },
  {
    "path": "vendor/clue/socket-raw/src/Socket.php",
    "content": "<?php\n\nnamespace Socket\\Raw;\n\n/**\n * Simple and lightweight OOP wrapper for the low-level sockets extension (ext-sockets)\n *\n * @author clue\n * @link https://github.com/clue/php-socket-raw\n */\nclass Socket\n{\n    /**\n     * reference to actual socket resource\n     *\n     * @var \\Socket|resource\n     */\n    private $resource;\n\n    /**\n     * instanciate socket wrapper for given socket resource\n     *\n     * should usually not be called manually, see Factory\n     *\n     * @param \\Socket|resource $resource\n     * @see Factory as the preferred (and simplest) way to construct socket instances\n     */\n    public function __construct($resource)\n    {\n        $this->resource = $resource;\n    }\n\n    /**\n     * get actual socket resource\n     *\n     * @return \\Socket|resource returns the socket resource (a `Socket` object as of PHP 8)\n     */\n    public function getResource()\n    {\n        return $this->resource;\n    }\n\n    /**\n     * accept an incomming connection on this listening socket\n     *\n     * @return \\Socket\\Raw\\Socket new connected socket used for communication\n     * @throws Exception on error, if this is not a listening socket or there's no connection pending\n     * @throws \\Error PHP 8 only: throws \\Error when socket is invalid\n     * @see self::selectRead() to check if this listening socket can accept()\n     * @see Factory::createServer() to create a listening socket\n     * @see self::listen() has to be called first\n     * @uses socket_accept()\n     */\n    public function accept()\n    {\n        $resource = @socket_accept($this->resource);\n        if ($resource === false) {\n            throw Exception::createFromGlobalSocketOperation();\n        }\n        return new Socket($resource);\n    }\n\n    /**\n     * binds a name/address/path to this socket\n     *\n     * has to be called before issuing connect() or listen()\n     *\n     * @param string $address either of IPv4:port, hostname:port, [IPv6]:port, unix-path\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses socket_bind()\n     */\n    public function bind($address)\n    {\n        $ret = @socket_bind($this->resource, $this->unformatAddress($address, $port), $port);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this;\n    }\n\n    /**\n     * close this socket\n     *\n     * ATTENTION: make sure to NOT re-use this socket instance after closing it!\n     * its socket resource remains closed and most further operations will fail!\n     *\n     * @return self $this (chainable)\n     * @throws \\Error PHP 8 only: throws \\Error when socket is invalid\n     * @see self::shutdown() should be called before closing socket\n     * @uses socket_close()\n     */\n    public function close()\n    {\n        socket_close($this->resource);\n        return $this;\n    }\n\n    /**\n     * initiate a connection to given address\n     *\n     * @param string $address either of IPv4:port, hostname:port, [IPv6]:port, unix-path\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses socket_connect()\n     */\n    public function connect($address)\n    {\n        $ret = @socket_connect($this->resource, $this->unformatAddress($address, $port), $port);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this;\n    }\n\n    /**\n     * Initiates a new connection to given address, wait for up to $timeout seconds\n     *\n     * The given $timeout parameter is an upper bound, a maximum time to wait\n     * for the connection to be either accepted or rejected.\n     *\n     * The resulting socket resource will be set to non-blocking mode,\n     * regardless of its previous state and whether this method succedes or\n     * if it fails. Make sure to reset with `setBlocking(true)` if you want to\n     * continue using blocking calls.\n     *\n     * @param string $address either of IPv4:port, hostname:port, [IPv6]:port, unix-path\n     * @param float  $timeout maximum time to wait (in seconds)\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses self::setBlocking() to enable non-blocking mode\n     * @uses self::connect() to initiate the connection\n     * @uses self::selectWrite() to wait for the connection to complete\n     * @uses self::assertAlive() to check connection state\n     */\n    public function connectTimeout($address, $timeout)\n    {\n        $this->setBlocking(false);\n\n        try {\n            // socket is non-blocking, so connect should emit EINPROGRESS\n            $this->connect($address);\n\n            // socket is already connected immediately?\n            return $this;\n        } catch (Exception $e) {\n            // non-blocking connect() should be EINPROGRESS (or EWOULDBLOCK on Windows) => otherwise re-throw\n            if ($e->getCode() !== SOCKET_EINPROGRESS && $e->getCode() !== SOCKET_EWOULDBLOCK) {\n                throw $e;\n            }\n\n            // connection should be completed (or rejected) within timeout\n            if ($this->selectWrite($timeout) === false) {\n                throw new Exception('Timed out while waiting for connection', SOCKET_ETIMEDOUT);\n            }\n\n            // confirm connection success (or fail if connected has been rejected)\n            $this->assertAlive();\n\n            return $this;\n        }\n    }\n\n    /**\n     * get socket option\n     *\n     * @param int $level\n     * @param int $optname\n     * @return mixed\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses socket_get_option()\n     */\n    public function getOption($level, $optname)\n    {\n        $value = @socket_get_option($this->resource, $level, $optname);\n        if ($value === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $value;\n    }\n\n    /**\n     * get remote side's address/path\n     *\n     * @return string\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket is invalid\n     * @uses socket_getpeername()\n     */\n    public function getPeerName()\n    {\n        $ret = @socket_getpeername($this->resource, $address, $port);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this->formatAddress($address, $port);\n    }\n\n    /**\n     * get local side's address/path\n     *\n     * @return string\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket is invalid\n     * @uses socket_getsockname()\n     */\n    public function getSockName()\n    {\n        $ret = @socket_getsockname($this->resource, $address, $port);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this->formatAddress($address, $port);\n    }\n\n    /**\n     * start listen for incoming connections\n     *\n     * @param int $backlog maximum number of incoming connections to be queued\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::bind() has to be called first to bind name to socket\n     * @uses socket_listen()\n     */\n    public function listen($backlog = 0)\n    {\n        $ret = @socket_listen($this->resource, $backlog);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this;\n    }\n\n    /**\n     * read up to $length bytes from connect()ed / accept()ed socket\n     *\n     * The $type parameter specifies if this should use either binary safe reading\n     * (PHP_BINARY_READ, the default) or stop at CR or LF characters (PHP_NORMAL_READ)\n     *\n     * @param int $length maximum length to read\n     * @param int $type   either of PHP_BINARY_READ (the default) or PHP_NORMAL_READ\n     * @return string\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::recv() if you need to pass flags\n     * @uses socket_read()\n     */\n    public function read($length, $type = PHP_BINARY_READ)\n    {\n        $data = @socket_read($this->resource, $length, $type);\n        if ($data === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $data;\n    }\n\n    /**\n     * receive up to $length bytes from connect()ed / accept()ed socket\n     *\n     * @param int $length maximum length to read\n     * @param int $flags\n     * @return string\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::read() if you do not need to pass $flags\n     * @see self::recvFrom() if your socket is not connect()ed\n     * @uses socket_recv()\n     */\n    public function recv($length, $flags)\n    {\n        $ret = @socket_recv($this->resource, $buffer, $length, $flags);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $buffer;\n    }\n\n    /**\n     * receive up to $length bytes from socket\n     *\n     * @param int    $length maximum length to read\n     * @param int    $flags\n     * @param string $remote reference will be filled with remote/peer address/path\n     * @return string\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::recv() if your socket is connect()ed\n     * @uses socket_recvfrom()\n     */\n    public function recvFrom($length, $flags, &$remote)\n    {\n        $ret = @socket_recvfrom($this->resource, $buffer, $length, $flags, $address, $port);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        $remote = $this->formatAddress($address, $port);\n        return $buffer;\n    }\n\n    /**\n     * check socket to see if a read/recv/revFrom will not block\n     *\n     * @param float|null $sec maximum time to wait (in seconds), 0 = immediate polling, null = no limit\n     * @return boolean true = socket ready (read will not block), false = timeout expired, socket is not ready\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses socket_select()\n     */\n    public function selectRead($sec = 0)\n    {\n        $usec = $sec === null ? null : (int) (($sec - floor($sec)) * 1000000);\n        $r = array($this->resource);\n        $n = null;\n        $ret = @socket_select($r, $n, $n, $sec === null ? null : (int) $sec, $usec);\n        if ($ret === false) {\n            throw Exception::createFromGlobalSocketOperation('Failed to select socket for reading');\n        }\n        return !!$ret;\n    }\n\n    /**\n     * check socket to see if a write/send/sendTo will not block\n     *\n     * @param float|null $sec maximum time to wait (in seconds), 0 = immediate polling, null = no limit\n     * @return boolean true = socket ready (write will not block), false = timeout expired, socket is not ready\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses socket_select()\n     */\n    public function selectWrite($sec = 0)\n    {\n        $usec = $sec === null ? null : (int) (($sec - floor($sec)) * 1000000);\n        $w = array($this->resource);\n        $n = null;\n        $ret = @socket_select($n, $w, $n, $sec === null ? null : (int) $sec, $usec);\n        if ($ret === false) {\n            throw Exception::createFromGlobalSocketOperation('Failed to select socket for writing');\n        }\n        return !!$ret;\n    }\n\n    /**\n     * send given $buffer to connect()ed / accept()ed socket\n     *\n     * @param string $buffer\n     * @param int    $flags\n     * @return int number of bytes actually written (make sure to check against given buffer length!)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::write() if you do not need to pass $flags\n     * @see self::sendTo() if your socket is not connect()ed\n     * @uses socket_send()\n     */\n    public function send($buffer, $flags)\n    {\n        $ret = @socket_send($this->resource, $buffer, strlen($buffer), $flags);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $ret;\n    }\n\n    /**\n     * send given $buffer to socket\n     *\n     * @param string $buffer\n     * @param int    $flags\n     * @param string $remote remote/peer address/path\n     * @return int number of bytes actually written\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::send() if your socket is connect()ed\n     * @uses socket_sendto()\n     */\n    public function sendTo($buffer, $flags, $remote)\n    {\n        $ret = @socket_sendto($this->resource, $buffer, strlen($buffer), $flags, $this->unformatAddress($remote, $port), $port);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $ret;\n    }\n\n    /**\n     * enable/disable blocking/nonblocking mode (O_NONBLOCK flag)\n     *\n     * @param boolean $toggle\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @uses socket_set_block()\n     * @uses socket_set_nonblock()\n     */\n    public function setBlocking($toggle = true)\n    {\n        $ret = $toggle ? @socket_set_block($this->resource) : @socket_set_nonblock($this->resource);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this;\n    }\n\n    /**\n     * set socket option\n     *\n     * @param int   $level\n     * @param int   $optname\n     * @param mixed $optval\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::getOption()\n     * @uses socket_set_option()\n     */\n    public function setOption($level, $optname, $optval)\n    {\n        $ret = @socket_set_option($this->resource, $level, $optname, $optval);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this;\n    }\n\n    /**\n     * shuts down socket for receiving, sending or both\n     *\n     * @param int $how 0 = shutdown reading, 1 = shutdown writing, 2 = shutdown reading and writing\n     * @return self $this (chainable)\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::close()\n     * @uses socket_shutdown()\n     */\n    public function shutdown($how = 2)\n    {\n        $ret = @socket_shutdown($this->resource, $how);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $this;\n    }\n\n    /**\n     * write $buffer to connect()ed / accept()ed socket\n     *\n     * @param string $buffer\n     * @return int number of bytes actually written\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket or arguments are invalid\n     * @see self::send() if you need to pass flags\n     * @uses socket_write()\n     */\n    public function write($buffer)\n    {\n        $ret = @socket_write($this->resource, $buffer);\n        if ($ret === false) {\n            throw Exception::createFromSocketResource($this->resource);\n        }\n        return $ret;\n    }\n\n    /**\n     * get socket type as passed to socket_create()\n     *\n     * @return int usually either SOCK_STREAM or SOCK_DGRAM\n     * @throws Exception on error\n     * @throws \\Error PHP 8 only: throws \\Error when socket is invalid\n     * @uses self::getOption()\n     */\n    public function getType()\n    {\n        return $this->getOption(SOL_SOCKET, SO_TYPE);\n    }\n\n    /**\n     * assert that this socket is alive and its error code is 0\n     *\n     * This will fetch and reset the current socket error code from the\n     * socket and options and will throw an Exception along with error\n     * message and code if the code is not 0, i.e. if it does indicate\n     * an error situation.\n     *\n     * Calling this method should not be needed in most cases and is\n     * likely to not throw an Exception. Each socket operation like\n     * connect(), send(), etc. will throw a dedicated Exception in case\n     * of an error anyway.\n     *\n     * @return self $this (chainable)\n     * @throws Exception if error code is not 0\n     * @throws \\Error PHP 8 only: throws \\Error when socket is invalid\n     * @uses self::getOption() to retrieve and clear current error code\n     * @uses self::getErrorMessage() to translate error code to\n     */\n    public function assertAlive()\n    {\n        $code = $this->getOption(SOL_SOCKET, SO_ERROR);\n        if ($code !== 0) {\n            throw Exception::createFromCode($code, 'Socket error');\n        }\n        return $this;\n    }\n\n    /**\n     * format given address/host/path and port\n     *\n     * @param string $address\n     * @param int    $port\n     * @return string\n     */\n    protected function formatAddress($address, $port)\n    {\n        if ($port !== 0) {\n            if (strpos($address, ':') !== false) {\n                $address = '[' . $address . ']';\n            }\n            $address .= ':' . $port;\n        }\n        return $address;\n    }\n\n    /**\n     * format given address by splitting it into returned address and port set by reference\n     *\n     * @param string $address\n     * @param int $port\n     * @return string address with port removed\n     */\n    protected function unformatAddress($address, &$port)\n    {\n        // [::1]:2 => ::1 2\n        // test:2 => test 2\n        // ::1 => ::1\n        // test => test\n\n        $colon = strrpos($address, ':');\n\n        // there is a colon and this is the only colon or there's a closing IPv6 bracket right before it\n        if ($colon !== false && (strpos($address, ':') === $colon || strpos($address, ']') === ($colon - 1))) {\n            $port = (int)substr($address, $colon + 1);\n            $address = substr($address, 0, $colon);\n\n            // remove IPv6 square brackets\n            if (substr($address, 0, 1) === '[') {\n                $address = substr($address, 1, -1);\n            }\n        }\n        return $address;\n    }\n}\n"
  },
  {
    "path": "vendor/composer/ClassLoader.php",
    "content": "<?php\n\n/*\n * This file is part of Composer.\n *\n * (c) Nils Adermann <naderman@naderman.de>\n *     Jordi Boggiano <j.boggiano@seld.be>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Composer\\Autoload;\n\n/**\n * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.\n *\n *     $loader = new \\Composer\\Autoload\\ClassLoader();\n *\n *     // register classes with namespaces\n *     $loader->add('Symfony\\Component', __DIR__.'/component');\n *     $loader->add('Symfony',           __DIR__.'/framework');\n *\n *     // activate the autoloader\n *     $loader->register();\n *\n *     // to enable searching the include path (eg. for PEAR packages)\n *     $loader->setUseIncludePath(true);\n *\n * In this example, if you try to use a class in the Symfony\\Component\n * namespace or one of its children (Symfony\\Component\\Console for instance),\n * the autoloader will first look for the class under the component/\n * directory, and it will then fallback to the framework/ directory if not\n * found before giving up.\n *\n * This class is loosely based on the Symfony UniversalClassLoader.\n *\n * @author Fabien Potencier <fabien@symfony.com>\n * @author Jordi Boggiano <j.boggiano@seld.be>\n * @see    https://www.php-fig.org/psr/psr-0/\n * @see    https://www.php-fig.org/psr/psr-4/\n */\nclass ClassLoader\n{\n    /** @var ?string */\n    private $vendorDir;\n\n    // PSR-4\n    /**\n     * @var array[]\n     * @psalm-var array<string, array<string, int>>\n     */\n    private $prefixLengthsPsr4 = array();\n    /**\n     * @var array[]\n     * @psalm-var array<string, array<int, string>>\n     */\n    private $prefixDirsPsr4 = array();\n    /**\n     * @var array[]\n     * @psalm-var array<string, string>\n     */\n    private $fallbackDirsPsr4 = array();\n\n    // PSR-0\n    /**\n     * @var array[]\n     * @psalm-var array<string, array<string, string[]>>\n     */\n    private $prefixesPsr0 = array();\n    /**\n     * @var array[]\n     * @psalm-var array<string, string>\n     */\n    private $fallbackDirsPsr0 = array();\n\n    /** @var bool */\n    private $useIncludePath = false;\n\n    /**\n     * @var string[]\n     * @psalm-var array<string, string>\n     */\n    private $classMap = array();\n\n    /** @var bool */\n    private $classMapAuthoritative = false;\n\n    /**\n     * @var bool[]\n     * @psalm-var array<string, bool>\n     */\n    private $missingClasses = array();\n\n    /** @var ?string */\n    private $apcuPrefix;\n\n    /**\n     * @var self[]\n     */\n    private static $registeredLoaders = array();\n\n    /**\n     * @param ?string $vendorDir\n     */\n    public function __construct($vendorDir = null)\n    {\n        $this->vendorDir = $vendorDir;\n    }\n\n    /**\n     * @return string[]\n     */\n    public function getPrefixes()\n    {\n        if (!empty($this->prefixesPsr0)) {\n            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));\n        }\n\n        return array();\n    }\n\n    /**\n     * @return array[]\n     * @psalm-return array<string, array<int, string>>\n     */\n    public function getPrefixesPsr4()\n    {\n        return $this->prefixDirsPsr4;\n    }\n\n    /**\n     * @return array[]\n     * @psalm-return array<string, string>\n     */\n    public function getFallbackDirs()\n    {\n        return $this->fallbackDirsPsr0;\n    }\n\n    /**\n     * @return array[]\n     * @psalm-return array<string, string>\n     */\n    public function getFallbackDirsPsr4()\n    {\n        return $this->fallbackDirsPsr4;\n    }\n\n    /**\n     * @return string[] Array of classname => path\n     * @psalm-var array<string, string>\n     */\n    public function getClassMap()\n    {\n        return $this->classMap;\n    }\n\n    /**\n     * @param string[] $classMap Class to filename map\n     * @psalm-param array<string, string> $classMap\n     *\n     * @return void\n     */\n    public function addClassMap(array $classMap)\n    {\n        if ($this->classMap) {\n            $this->classMap = array_merge($this->classMap, $classMap);\n        } else {\n            $this->classMap = $classMap;\n        }\n    }\n\n    /**\n     * Registers a set of PSR-0 directories for a given prefix, either\n     * appending or prepending to the ones previously set for this prefix.\n     *\n     * @param string          $prefix  The prefix\n     * @param string[]|string $paths   The PSR-0 root directories\n     * @param bool            $prepend Whether to prepend the directories\n     *\n     * @return void\n     */\n    public function add($prefix, $paths, $prepend = false)\n    {\n        if (!$prefix) {\n            if ($prepend) {\n                $this->fallbackDirsPsr0 = array_merge(\n                    (array) $paths,\n                    $this->fallbackDirsPsr0\n                );\n            } else {\n                $this->fallbackDirsPsr0 = array_merge(\n                    $this->fallbackDirsPsr0,\n                    (array) $paths\n                );\n            }\n\n            return;\n        }\n\n        $first = $prefix[0];\n        if (!isset($this->prefixesPsr0[$first][$prefix])) {\n            $this->prefixesPsr0[$first][$prefix] = (array) $paths;\n\n            return;\n        }\n        if ($prepend) {\n            $this->prefixesPsr0[$first][$prefix] = array_merge(\n                (array) $paths,\n                $this->prefixesPsr0[$first][$prefix]\n            );\n        } else {\n            $this->prefixesPsr0[$first][$prefix] = array_merge(\n                $this->prefixesPsr0[$first][$prefix],\n                (array) $paths\n            );\n        }\n    }\n\n    /**\n     * Registers a set of PSR-4 directories for a given namespace, either\n     * appending or prepending to the ones previously set for this namespace.\n     *\n     * @param string          $prefix  The prefix/namespace, with trailing '\\\\'\n     * @param string[]|string $paths   The PSR-4 base directories\n     * @param bool            $prepend Whether to prepend the directories\n     *\n     * @throws \\InvalidArgumentException\n     *\n     * @return void\n     */\n    public function addPsr4($prefix, $paths, $prepend = false)\n    {\n        if (!$prefix) {\n            // Register directories for the root namespace.\n            if ($prepend) {\n                $this->fallbackDirsPsr4 = array_merge(\n                    (array) $paths,\n                    $this->fallbackDirsPsr4\n                );\n            } else {\n                $this->fallbackDirsPsr4 = array_merge(\n                    $this->fallbackDirsPsr4,\n                    (array) $paths\n                );\n            }\n        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {\n            // Register directories for a new namespace.\n            $length = strlen($prefix);\n            if ('\\\\' !== $prefix[$length - 1]) {\n                throw new \\InvalidArgumentException(\"A non-empty PSR-4 prefix must end with a namespace separator.\");\n            }\n            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;\n            $this->prefixDirsPsr4[$prefix] = (array) $paths;\n        } elseif ($prepend) {\n            // Prepend directories for an already registered namespace.\n            $this->prefixDirsPsr4[$prefix] = array_merge(\n                (array) $paths,\n                $this->prefixDirsPsr4[$prefix]\n            );\n        } else {\n            // Append directories for an already registered namespace.\n            $this->prefixDirsPsr4[$prefix] = array_merge(\n                $this->prefixDirsPsr4[$prefix],\n                (array) $paths\n            );\n        }\n    }\n\n    /**\n     * Registers a set of PSR-0 directories for a given prefix,\n     * replacing any others previously set for this prefix.\n     *\n     * @param string          $prefix The prefix\n     * @param string[]|string $paths  The PSR-0 base directories\n     *\n     * @return void\n     */\n    public function set($prefix, $paths)\n    {\n        if (!$prefix) {\n            $this->fallbackDirsPsr0 = (array) $paths;\n        } else {\n            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;\n        }\n    }\n\n    /**\n     * Registers a set of PSR-4 directories for a given namespace,\n     * replacing any others previously set for this namespace.\n     *\n     * @param string          $prefix The prefix/namespace, with trailing '\\\\'\n     * @param string[]|string $paths  The PSR-4 base directories\n     *\n     * @throws \\InvalidArgumentException\n     *\n     * @return void\n     */\n    public function setPsr4($prefix, $paths)\n    {\n        if (!$prefix) {\n            $this->fallbackDirsPsr4 = (array) $paths;\n        } else {\n            $length = strlen($prefix);\n            if ('\\\\' !== $prefix[$length - 1]) {\n                throw new \\InvalidArgumentException(\"A non-empty PSR-4 prefix must end with a namespace separator.\");\n            }\n            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;\n            $this->prefixDirsPsr4[$prefix] = (array) $paths;\n        }\n    }\n\n    /**\n     * Turns on searching the include path for class files.\n     *\n     * @param bool $useIncludePath\n     *\n     * @return void\n     */\n    public function setUseIncludePath($useIncludePath)\n    {\n        $this->useIncludePath = $useIncludePath;\n    }\n\n    /**\n     * Can be used to check if the autoloader uses the include path to check\n     * for classes.\n     *\n     * @return bool\n     */\n    public function getUseIncludePath()\n    {\n        return $this->useIncludePath;\n    }\n\n    /**\n     * Turns off searching the prefix and fallback directories for classes\n     * that have not been registered with the class map.\n     *\n     * @param bool $classMapAuthoritative\n     *\n     * @return void\n     */\n    public function setClassMapAuthoritative($classMapAuthoritative)\n    {\n        $this->classMapAuthoritative = $classMapAuthoritative;\n    }\n\n    /**\n     * Should class lookup fail if not found in the current class map?\n     *\n     * @return bool\n     */\n    public function isClassMapAuthoritative()\n    {\n        return $this->classMapAuthoritative;\n    }\n\n    /**\n     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.\n     *\n     * @param string|null $apcuPrefix\n     *\n     * @return void\n     */\n    public function setApcuPrefix($apcuPrefix)\n    {\n        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;\n    }\n\n    /**\n     * The APCu prefix in use, or null if APCu caching is not enabled.\n     *\n     * @return string|null\n     */\n    public function getApcuPrefix()\n    {\n        return $this->apcuPrefix;\n    }\n\n    /**\n     * Registers this instance as an autoloader.\n     *\n     * @param bool $prepend Whether to prepend the autoloader or not\n     *\n     * @return void\n     */\n    public function register($prepend = false)\n    {\n        spl_autoload_register(array($this, 'loadClass'), true, $prepend);\n\n        if (null === $this->vendorDir) {\n            return;\n        }\n\n        if ($prepend) {\n            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;\n        } else {\n            unset(self::$registeredLoaders[$this->vendorDir]);\n            self::$registeredLoaders[$this->vendorDir] = $this;\n        }\n    }\n\n    /**\n     * Unregisters this instance as an autoloader.\n     *\n     * @return void\n     */\n    public function unregister()\n    {\n        spl_autoload_unregister(array($this, 'loadClass'));\n\n        if (null !== $this->vendorDir) {\n            unset(self::$registeredLoaders[$this->vendorDir]);\n        }\n    }\n\n    /**\n     * Loads the given class or interface.\n     *\n     * @param  string    $class The name of the class\n     * @return true|null True if loaded, null otherwise\n     */\n    public function loadClass($class)\n    {\n        if ($file = $this->findFile($class)) {\n            includeFile($file);\n\n            return true;\n        }\n\n        return null;\n    }\n\n    /**\n     * Finds the path to the file where the class is defined.\n     *\n     * @param string $class The name of the class\n     *\n     * @return string|false The path if found, false otherwise\n     */\n    public function findFile($class)\n    {\n        // class map lookup\n        if (isset($this->classMap[$class])) {\n            return $this->classMap[$class];\n        }\n        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {\n            return false;\n        }\n        if (null !== $this->apcuPrefix) {\n            $file = apcu_fetch($this->apcuPrefix.$class, $hit);\n            if ($hit) {\n                return $file;\n            }\n        }\n\n        $file = $this->findFileWithExtension($class, '.php');\n\n        // Search for Hack files if we are running on HHVM\n        if (false === $file && defined('HHVM_VERSION')) {\n            $file = $this->findFileWithExtension($class, '.hh');\n        }\n\n        if (null !== $this->apcuPrefix) {\n            apcu_add($this->apcuPrefix.$class, $file);\n        }\n\n        if (false === $file) {\n            // Remember that this class does not exist.\n            $this->missingClasses[$class] = true;\n        }\n\n        return $file;\n    }\n\n    /**\n     * Returns the currently registered loaders indexed by their corresponding vendor directories.\n     *\n     * @return self[]\n     */\n    public static function getRegisteredLoaders()\n    {\n        return self::$registeredLoaders;\n    }\n\n    /**\n     * @param  string       $class\n     * @param  string       $ext\n     * @return string|false\n     */\n    private function findFileWithExtension($class, $ext)\n    {\n        // PSR-4 lookup\n        $logicalPathPsr4 = strtr($class, '\\\\', DIRECTORY_SEPARATOR) . $ext;\n\n        $first = $class[0];\n        if (isset($this->prefixLengthsPsr4[$first])) {\n            $subPath = $class;\n            while (false !== $lastPos = strrpos($subPath, '\\\\')) {\n                $subPath = substr($subPath, 0, $lastPos);\n                $search = $subPath . '\\\\';\n                if (isset($this->prefixDirsPsr4[$search])) {\n                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);\n                    foreach ($this->prefixDirsPsr4[$search] as $dir) {\n                        if (file_exists($file = $dir . $pathEnd)) {\n                            return $file;\n                        }\n                    }\n                }\n            }\n        }\n\n        // PSR-4 fallback dirs\n        foreach ($this->fallbackDirsPsr4 as $dir) {\n            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {\n                return $file;\n            }\n        }\n\n        // PSR-0 lookup\n        if (false !== $pos = strrpos($class, '\\\\')) {\n            // namespaced class name\n            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)\n                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);\n        } else {\n            // PEAR-like class name\n            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;\n        }\n\n        if (isset($this->prefixesPsr0[$first])) {\n            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {\n                if (0 === strpos($class, $prefix)) {\n                    foreach ($dirs as $dir) {\n                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {\n                            return $file;\n                        }\n                    }\n                }\n            }\n        }\n\n        // PSR-0 fallback dirs\n        foreach ($this->fallbackDirsPsr0 as $dir) {\n            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {\n                return $file;\n            }\n        }\n\n        // PSR-0 include paths.\n        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {\n            return $file;\n        }\n\n        return false;\n    }\n}\n\n/**\n * Scope isolated include.\n *\n * Prevents access to $this/self from included files.\n *\n * @param  string $file\n * @return void\n * @private\n */\nfunction includeFile($file)\n{\n    include $file;\n}\n"
  },
  {
    "path": "vendor/composer/InstalledVersions.php",
    "content": "<?php\n\n/*\n * This file is part of Composer.\n *\n * (c) Nils Adermann <naderman@naderman.de>\n *     Jordi Boggiano <j.boggiano@seld.be>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Composer;\n\nuse Composer\\Autoload\\ClassLoader;\nuse Composer\\Semver\\VersionParser;\n\n/**\n * This class is copied in every Composer installed project and available to all\n *\n * See also https://getcomposer.org/doc/07-runtime.md#installed-versions\n *\n * To require its presence, you can require `composer-runtime-api ^2.0`\n */\nclass InstalledVersions\n{\n    /**\n     * @var mixed[]|null\n     * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null\n     */\n    private static $installed;\n\n    /**\n     * @var bool|null\n     */\n    private static $canGetVendors;\n\n    /**\n     * @var array[]\n     * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>\n     */\n    private static $installedByVendor = array();\n\n    /**\n     * Returns a list of all package names which are present, either by being installed, replaced or provided\n     *\n     * @return string[]\n     * @psalm-return list<string>\n     */\n    public static function getInstalledPackages()\n    {\n        $packages = array();\n        foreach (self::getInstalled() as $installed) {\n            $packages[] = array_keys($installed['versions']);\n        }\n\n        if (1 === \\count($packages)) {\n            return $packages[0];\n        }\n\n        return array_keys(array_flip(\\call_user_func_array('array_merge', $packages)));\n    }\n\n    /**\n     * Returns a list of all package names with a specific type e.g. 'library'\n     *\n     * @param  string   $type\n     * @return string[]\n     * @psalm-return list<string>\n     */\n    public static function getInstalledPackagesByType($type)\n    {\n        $packagesByType = array();\n\n        foreach (self::getInstalled() as $installed) {\n            foreach ($installed['versions'] as $name => $package) {\n                if (isset($package['type']) && $package['type'] === $type) {\n                    $packagesByType[] = $name;\n                }\n            }\n        }\n\n        return $packagesByType;\n    }\n\n    /**\n     * Checks whether the given package is installed\n     *\n     * This also returns true if the package name is provided or replaced by another package\n     *\n     * @param  string $packageName\n     * @param  bool   $includeDevRequirements\n     * @return bool\n     */\n    public static function isInstalled($packageName, $includeDevRequirements = true)\n    {\n        foreach (self::getInstalled() as $installed) {\n            if (isset($installed['versions'][$packageName])) {\n                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Checks whether the given package satisfies a version constraint\n     *\n     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:\n     *\n     *   Composer\\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')\n     *\n     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality\n     * @param  string        $packageName\n     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package\n     * @return bool\n     */\n    public static function satisfies(VersionParser $parser, $packageName, $constraint)\n    {\n        $constraint = $parser->parseConstraints($constraint);\n        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));\n\n        return $provided->matches($constraint);\n    }\n\n    /**\n     * Returns a version constraint representing all the range(s) which are installed for a given package\n     *\n     * It is easier to use this via isInstalled() with the $constraint argument if you need to check\n     * whether a given version of a package is installed, and not just whether it exists\n     *\n     * @param  string $packageName\n     * @return string Version constraint usable with composer/semver\n     */\n    public static function getVersionRanges($packageName)\n    {\n        foreach (self::getInstalled() as $installed) {\n            if (!isset($installed['versions'][$packageName])) {\n                continue;\n            }\n\n            $ranges = array();\n            if (isset($installed['versions'][$packageName]['pretty_version'])) {\n                $ranges[] = $installed['versions'][$packageName]['pretty_version'];\n            }\n            if (array_key_exists('aliases', $installed['versions'][$packageName])) {\n                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);\n            }\n            if (array_key_exists('replaced', $installed['versions'][$packageName])) {\n                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);\n            }\n            if (array_key_exists('provided', $installed['versions'][$packageName])) {\n                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);\n            }\n\n            return implode(' || ', $ranges);\n        }\n\n        throw new \\OutOfBoundsException('Package \"' . $packageName . '\" is not installed');\n    }\n\n    /**\n     * @param  string      $packageName\n     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present\n     */\n    public static function getVersion($packageName)\n    {\n        foreach (self::getInstalled() as $installed) {\n            if (!isset($installed['versions'][$packageName])) {\n                continue;\n            }\n\n            if (!isset($installed['versions'][$packageName]['version'])) {\n                return null;\n            }\n\n            return $installed['versions'][$packageName]['version'];\n        }\n\n        throw new \\OutOfBoundsException('Package \"' . $packageName . '\" is not installed');\n    }\n\n    /**\n     * @param  string      $packageName\n     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present\n     */\n    public static function getPrettyVersion($packageName)\n    {\n        foreach (self::getInstalled() as $installed) {\n            if (!isset($installed['versions'][$packageName])) {\n                continue;\n            }\n\n            if (!isset($installed['versions'][$packageName]['pretty_version'])) {\n                return null;\n            }\n\n            return $installed['versions'][$packageName]['pretty_version'];\n        }\n\n        throw new \\OutOfBoundsException('Package \"' . $packageName . '\" is not installed');\n    }\n\n    /**\n     * @param  string      $packageName\n     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference\n     */\n    public static function getReference($packageName)\n    {\n        foreach (self::getInstalled() as $installed) {\n            if (!isset($installed['versions'][$packageName])) {\n                continue;\n            }\n\n            if (!isset($installed['versions'][$packageName]['reference'])) {\n                return null;\n            }\n\n            return $installed['versions'][$packageName]['reference'];\n        }\n\n        throw new \\OutOfBoundsException('Package \"' . $packageName . '\" is not installed');\n    }\n\n    /**\n     * @param  string      $packageName\n     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.\n     */\n    public static function getInstallPath($packageName)\n    {\n        foreach (self::getInstalled() as $installed) {\n            if (!isset($installed['versions'][$packageName])) {\n                continue;\n            }\n\n            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;\n        }\n\n        throw new \\OutOfBoundsException('Package \"' . $packageName . '\" is not installed');\n    }\n\n    /**\n     * @return array\n     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}\n     */\n    public static function getRootPackage()\n    {\n        $installed = self::getInstalled();\n\n        return $installed[0]['root'];\n    }\n\n    /**\n     * Returns the raw installed.php data for custom implementations\n     *\n     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.\n     * @return array[]\n     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}\n     */\n    public static function getRawData()\n    {\n        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);\n\n        if (null === self::$installed) {\n            // only require the installed.php file if this file is loaded from its dumped location,\n            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937\n            if (substr(__DIR__, -8, 1) !== 'C') {\n                self::$installed = include __DIR__ . '/installed.php';\n            } else {\n                self::$installed = array();\n            }\n        }\n\n        return self::$installed;\n    }\n\n    /**\n     * Returns the raw data of all installed.php which are currently loaded for custom implementations\n     *\n     * @return array[]\n     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>\n     */\n    public static function getAllRawData()\n    {\n        return self::getInstalled();\n    }\n\n    /**\n     * Lets you reload the static array from another file\n     *\n     * This is only useful for complex integrations in which a project needs to use\n     * this class but then also needs to execute another project's autoloader in process,\n     * and wants to ensure both projects have access to their version of installed.php.\n     *\n     * A typical case would be PHPUnit, where it would need to make sure it reads all\n     * the data it needs from this class, then call reload() with\n     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure\n     * the project in which it runs can then also use this class safely, without\n     * interference between PHPUnit's dependencies and the project's dependencies.\n     *\n     * @param  array[] $data A vendor/composer/installed.php data set\n     * @return void\n     *\n     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data\n     */\n    public static function reload($data)\n    {\n        self::$installed = $data;\n        self::$installedByVendor = array();\n    }\n\n    /**\n     * @return array[]\n     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>\n     */\n    private static function getInstalled()\n    {\n        if (null === self::$canGetVendors) {\n            self::$canGetVendors = method_exists('Composer\\Autoload\\ClassLoader', 'getRegisteredLoaders');\n        }\n\n        $installed = array();\n\n        if (self::$canGetVendors) {\n            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {\n                if (isset(self::$installedByVendor[$vendorDir])) {\n                    $installed[] = self::$installedByVendor[$vendorDir];\n                } elseif (is_file($vendorDir.'/composer/installed.php')) {\n                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';\n                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\\\', '/') === strtr(__DIR__, '\\\\', '/')) {\n                        self::$installed = $installed[count($installed) - 1];\n                    }\n                }\n            }\n        }\n\n        if (null === self::$installed) {\n            // only require the installed.php file if this file is loaded from its dumped location,\n            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937\n            if (substr(__DIR__, -8, 1) !== 'C') {\n                self::$installed = require __DIR__ . '/installed.php';\n            } else {\n                self::$installed = array();\n            }\n        }\n        $installed[] = self::$installed;\n\n        return $installed;\n    }\n}\n"
  },
  {
    "path": "vendor/composer/LICENSE",
    "content": "\nCopyright (c) Nils Adermann, Jordi Boggiano\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "vendor/composer/autoload_classmap.php",
    "content": "<?php\n\n// autoload_classmap.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($vendorDir);\n\nreturn array(\n    'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',\n    'Callback' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'CallbackBody' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'CallbackParam' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'CallbackParameterToReference' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'CallbackReturnReference' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'CallbackReturnValue' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'Composer\\\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',\n    'DOMDocumentWrapper' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'DOMEvent' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'ICallbackNamed' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',\n    'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',\n    'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',\n    'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',\n    'phpQuery' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'phpQueryEvents' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'phpQueryObject' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'phpQueryPlugins' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',\n    'vierbergenlars\\\\SemVer\\\\Internal\\\\Comparator' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n    'vierbergenlars\\\\SemVer\\\\Internal\\\\Exports' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n    'vierbergenlars\\\\SemVer\\\\Internal\\\\G' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n    'vierbergenlars\\\\SemVer\\\\Internal\\\\Range' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n    'vierbergenlars\\\\SemVer\\\\Internal\\\\SemVer' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n);\n"
  },
  {
    "path": "vendor/composer/autoload_files.php",
    "content": "<?php\n\n// autoload_files.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($vendorDir);\n\nreturn array(\n    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',\n    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',\n    '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',\n    '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',\n    'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',\n    '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',\n    '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',\n    'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',\n    'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',\n    'e3e8c4c1cab4cfd62813fc545d3f8fd8' => $baseDir . '/src/Helpers/helpers.php',\n    'cec6e86a76e2de36ba444b136c556738' => $baseDir . '/src/Helpers/helpers2.php',\n    '2bff77da563b10d387ae24ece393dbf8' => $baseDir . '/src/Controller/TaskController.php',\n    'f1725a1520f08083c7eff649cdc3b842' => $baseDir . '/includes/fatrat-apierror.php',\n    'cdb9e6f462e36295fe1bf579b2a1dda3' => $baseDir . '/includes/fatrat-spider.php',\n    '9a68f8051d2faaa0215116227f3a45cb' => $baseDir . '/includes/fatrat-options.php',\n    '34b08b32b9f432d320b702da89e5530f' => $baseDir . '/includes/fatrat-options-add-edit.php',\n    'fb3c91a70af6b35257192d4a6d2392ae' => $baseDir . '/includes/fatrat-data.php',\n    'd52d9cbc0431cd63756b2e9a82435d87' => $baseDir . '/includes/fatrat-data-detail.php',\n    '09dbf6463d6f9f0ea9e5e6ccb9c08826' => $baseDir . '/includes/fatrat-validation.php',\n    '37cbdf04d102eb8551fc92546c2b4ecd' => $baseDir . '/includes/fatrat-kit.php',\n    '0ce1b0616a57f9979a8cc825775b9783' => $baseDir . '/includes/fatrat-debugging.php',\n);\n"
  },
  {
    "path": "vendor/composer/autoload_namespaces.php",
    "content": "<?php\n\n// autoload_namespaces.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($vendorDir);\n\nreturn array(\n    'vierbergenlars\\\\SemVer\\\\' => array($vendorDir . '/vierbergenlars/php-semver/src'),\n    'vierbergenlars\\\\LibJs\\\\' => array($vendorDir . '/vierbergenlars/php-semver/src'),\n);\n"
  },
  {
    "path": "vendor/composer/autoload_psr4.php",
    "content": "<?php\n\n// autoload_psr4.php @generated by Composer\n\n$vendorDir = dirname(dirname(__FILE__));\n$baseDir = dirname($vendorDir);\n\nreturn array(\n    'Tightenco\\\\Collect\\\\' => array($vendorDir . '/tightenco/collect/src/Collect'),\n    'Symfony\\\\Polyfill\\\\Php80\\\\' => array($vendorDir . '/symfony/polyfill-php80'),\n    'Symfony\\\\Polyfill\\\\Mbstring\\\\' => array($vendorDir . '/symfony/polyfill-mbstring'),\n    'Symfony\\\\Component\\\\VarDumper\\\\' => array($vendorDir . '/symfony/var-dumper'),\n    'Symfony\\\\Component\\\\Process\\\\' => array($vendorDir . '/symfony/process'),\n    'Socket\\\\Raw\\\\' => array($vendorDir . '/clue/socket-raw/src'),\n    'QL\\\\Ext\\\\' => array($vendorDir . '/jaeger/querylist-puppeteer'),\n    'QL\\\\' => array($vendorDir . '/jaeger/querylist/src'),\n    'Psr\\\\SimpleCache\\\\' => array($vendorDir . '/psr/simple-cache/src'),\n    'Psr\\\\Log\\\\' => array($vendorDir . '/psr/log/Psr/Log'),\n    'Psr\\\\Http\\\\Message\\\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),\n    'Psr\\\\Http\\\\Client\\\\' => array($vendorDir . '/psr/http-client/src'),\n    'Psr\\\\Cache\\\\' => array($vendorDir . '/psr/cache/src'),\n    'Nesk\\\\Rialto\\\\' => array($vendorDir . '/nesk/rialto/src'),\n    'Nesk\\\\Puphpeteer\\\\' => array($vendorDir . '/nesk/puphpeteer/src'),\n    'League\\\\MimeTypeDetection\\\\' => array($vendorDir . '/league/mime-type-detection/src'),\n    'League\\\\Flysystem\\\\' => array($vendorDir . '/league/flysystem/src'),\n    'Jaeger\\\\' => array($vendorDir . '/jaeger/g-http/src'),\n    'GuzzleHttp\\\\Psr7\\\\' => array($vendorDir . '/guzzlehttp/psr7/src'),\n    'GuzzleHttp\\\\Promise\\\\' => array($vendorDir . '/guzzlehttp/promises/src'),\n    'GuzzleHttp\\\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),\n    'Cache\\\\TagInterop\\\\' => array($vendorDir . '/cache/tag-interop'),\n    'Cache\\\\Adapter\\\\Filesystem\\\\' => array($vendorDir . '/cache/filesystem-adapter'),\n    'Cache\\\\Adapter\\\\Common\\\\' => array($vendorDir . '/cache/adapter-common'),\n);\n"
  },
  {
    "path": "vendor/composer/autoload_real.php",
    "content": "<?php\n\n// autoload_real.php @generated by Composer\n\nclass ComposerAutoloaderInit15ad0a0b334e2ea46dbbf214582f0b16\n{\n    private static $loader;\n\n    public static function loadClassLoader($class)\n    {\n        if ('Composer\\Autoload\\ClassLoader' === $class) {\n            require __DIR__ . '/ClassLoader.php';\n        }\n    }\n\n    /**\n     * @return \\Composer\\Autoload\\ClassLoader\n     */\n    public static function getLoader()\n    {\n        if (null !== self::$loader) {\n            return self::$loader;\n        }\n\n        spl_autoload_register(array('ComposerAutoloaderInit15ad0a0b334e2ea46dbbf214582f0b16', 'loadClassLoader'), true, true);\n        self::$loader = $loader = new \\Composer\\Autoload\\ClassLoader(\\dirname(\\dirname(__FILE__)));\n        spl_autoload_unregister(array('ComposerAutoloaderInit15ad0a0b334e2ea46dbbf214582f0b16', 'loadClassLoader'));\n\n        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());\n        if ($useStaticLoader) {\n            require __DIR__ . '/autoload_static.php';\n\n            call_user_func(\\Composer\\Autoload\\ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16::getInitializer($loader));\n        } else {\n            $map = require __DIR__ . '/autoload_namespaces.php';\n            foreach ($map as $namespace => $path) {\n                $loader->set($namespace, $path);\n            }\n\n            $map = require __DIR__ . '/autoload_psr4.php';\n            foreach ($map as $namespace => $path) {\n                $loader->setPsr4($namespace, $path);\n            }\n\n            $classMap = require __DIR__ . '/autoload_classmap.php';\n            if ($classMap) {\n                $loader->addClassMap($classMap);\n            }\n        }\n\n        $loader->register(true);\n\n        if ($useStaticLoader) {\n            $includeFiles = Composer\\Autoload\\ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16::$files;\n        } else {\n            $includeFiles = require __DIR__ . '/autoload_files.php';\n        }\n        foreach ($includeFiles as $fileIdentifier => $file) {\n            composerRequire15ad0a0b334e2ea46dbbf214582f0b16($fileIdentifier, $file);\n        }\n\n        return $loader;\n    }\n}\n\nfunction composerRequire15ad0a0b334e2ea46dbbf214582f0b16($fileIdentifier, $file)\n{\n    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {\n        require $file;\n\n        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;\n    }\n}\n"
  },
  {
    "path": "vendor/composer/autoload_static.php",
    "content": "<?php\n\n// autoload_static.php @generated by Composer\n\nnamespace Composer\\Autoload;\n\nclass ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16\n{\n    public static $files = array (\n        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',\n        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',\n        '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',\n        '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',\n        'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',\n        '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',\n        '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',\n        'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',\n        'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',\n        'e3e8c4c1cab4cfd62813fc545d3f8fd8' => __DIR__ . '/../..' . '/src/Helpers/helpers.php',\n        'cec6e86a76e2de36ba444b136c556738' => __DIR__ . '/../..' . '/src/Helpers/helpers2.php',\n        '2bff77da563b10d387ae24ece393dbf8' => __DIR__ . '/../..' . '/src/Controller/TaskController.php',\n        'f1725a1520f08083c7eff649cdc3b842' => __DIR__ . '/../..' . '/includes/fatrat-apierror.php',\n        'cdb9e6f462e36295fe1bf579b2a1dda3' => __DIR__ . '/../..' . '/includes/fatrat-spider.php',\n        '9a68f8051d2faaa0215116227f3a45cb' => __DIR__ . '/../..' . '/includes/fatrat-options.php',\n        '34b08b32b9f432d320b702da89e5530f' => __DIR__ . '/../..' . '/includes/fatrat-options-add-edit.php',\n        'fb3c91a70af6b35257192d4a6d2392ae' => __DIR__ . '/../..' . '/includes/fatrat-data.php',\n        'd52d9cbc0431cd63756b2e9a82435d87' => __DIR__ . '/../..' . '/includes/fatrat-data-detail.php',\n        '09dbf6463d6f9f0ea9e5e6ccb9c08826' => __DIR__ . '/../..' . '/includes/fatrat-validation.php',\n        '37cbdf04d102eb8551fc92546c2b4ecd' => __DIR__ . '/../..' . '/includes/fatrat-kit.php',\n        '0ce1b0616a57f9979a8cc825775b9783' => __DIR__ . '/../..' . '/includes/fatrat-debugging.php',\n    );\n\n    public static $prefixLengthsPsr4 = array (\n        'T' => \n        array (\n            'Tightenco\\\\Collect\\\\' => 18,\n        ),\n        'S' => \n        array (\n            'Symfony\\\\Polyfill\\\\Php80\\\\' => 23,\n            'Symfony\\\\Polyfill\\\\Mbstring\\\\' => 26,\n            'Symfony\\\\Component\\\\VarDumper\\\\' => 28,\n            'Symfony\\\\Component\\\\Process\\\\' => 26,\n            'Socket\\\\Raw\\\\' => 11,\n        ),\n        'Q' => \n        array (\n            'QL\\\\Ext\\\\' => 7,\n            'QL\\\\' => 3,\n        ),\n        'P' => \n        array (\n            'Psr\\\\SimpleCache\\\\' => 16,\n            'Psr\\\\Log\\\\' => 8,\n            'Psr\\\\Http\\\\Message\\\\' => 17,\n            'Psr\\\\Http\\\\Client\\\\' => 16,\n            'Psr\\\\Cache\\\\' => 10,\n        ),\n        'N' => \n        array (\n            'Nesk\\\\Rialto\\\\' => 12,\n            'Nesk\\\\Puphpeteer\\\\' => 16,\n        ),\n        'L' => \n        array (\n            'League\\\\MimeTypeDetection\\\\' => 25,\n            'League\\\\Flysystem\\\\' => 17,\n        ),\n        'J' => \n        array (\n            'Jaeger\\\\' => 7,\n        ),\n        'G' => \n        array (\n            'GuzzleHttp\\\\Psr7\\\\' => 16,\n            'GuzzleHttp\\\\Promise\\\\' => 19,\n            'GuzzleHttp\\\\' => 11,\n        ),\n        'C' => \n        array (\n            'Cache\\\\TagInterop\\\\' => 17,\n            'Cache\\\\Adapter\\\\Filesystem\\\\' => 25,\n            'Cache\\\\Adapter\\\\Common\\\\' => 21,\n        ),\n    );\n\n    public static $prefixDirsPsr4 = array (\n        'Tightenco\\\\Collect\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/tightenco/collect/src/Collect',\n        ),\n        'Symfony\\\\Polyfill\\\\Php80\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/symfony/polyfill-php80',\n        ),\n        'Symfony\\\\Polyfill\\\\Mbstring\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',\n        ),\n        'Symfony\\\\Component\\\\VarDumper\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/symfony/var-dumper',\n        ),\n        'Symfony\\\\Component\\\\Process\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/symfony/process',\n        ),\n        'Socket\\\\Raw\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/clue/socket-raw/src',\n        ),\n        'QL\\\\Ext\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/jaeger/querylist-puppeteer',\n        ),\n        'QL\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/jaeger/querylist/src',\n        ),\n        'Psr\\\\SimpleCache\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/psr/simple-cache/src',\n        ),\n        'Psr\\\\Log\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/psr/log/Psr/Log',\n        ),\n        'Psr\\\\Http\\\\Message\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/psr/http-factory/src',\n            1 => __DIR__ . '/..' . '/psr/http-message/src',\n        ),\n        'Psr\\\\Http\\\\Client\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/psr/http-client/src',\n        ),\n        'Psr\\\\Cache\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/psr/cache/src',\n        ),\n        'Nesk\\\\Rialto\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/nesk/rialto/src',\n        ),\n        'Nesk\\\\Puphpeteer\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/nesk/puphpeteer/src',\n        ),\n        'League\\\\MimeTypeDetection\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/league/mime-type-detection/src',\n        ),\n        'League\\\\Flysystem\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/league/flysystem/src',\n        ),\n        'Jaeger\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/jaeger/g-http/src',\n        ),\n        'GuzzleHttp\\\\Psr7\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',\n        ),\n        'GuzzleHttp\\\\Promise\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',\n        ),\n        'GuzzleHttp\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',\n        ),\n        'Cache\\\\TagInterop\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/cache/tag-interop',\n        ),\n        'Cache\\\\Adapter\\\\Filesystem\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/cache/filesystem-adapter',\n        ),\n        'Cache\\\\Adapter\\\\Common\\\\' => \n        array (\n            0 => __DIR__ . '/..' . '/cache/adapter-common',\n        ),\n    );\n\n    public static $prefixesPsr0 = array (\n        'v' => \n        array (\n            'vierbergenlars\\\\SemVer\\\\' => \n            array (\n                0 => __DIR__ . '/..' . '/vierbergenlars/php-semver/src',\n            ),\n            'vierbergenlars\\\\LibJs\\\\' => \n            array (\n                0 => __DIR__ . '/..' . '/vierbergenlars/php-semver/src',\n            ),\n        ),\n    );\n\n    public static $classMap = array (\n        'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',\n        'Callback' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'CallbackBody' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'CallbackParam' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'CallbackParameterToReference' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'CallbackReturnReference' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'CallbackReturnValue' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'Composer\\\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',\n        'DOMDocumentWrapper' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'DOMEvent' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'ICallbackNamed' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',\n        'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',\n        'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',\n        'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',\n        'phpQuery' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'phpQueryEvents' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'phpQueryObject' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'phpQueryPlugins' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',\n        'vierbergenlars\\\\SemVer\\\\Internal\\\\Comparator' => __DIR__ . '/..' . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n        'vierbergenlars\\\\SemVer\\\\Internal\\\\Exports' => __DIR__ . '/..' . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n        'vierbergenlars\\\\SemVer\\\\Internal\\\\G' => __DIR__ . '/..' . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n        'vierbergenlars\\\\SemVer\\\\Internal\\\\Range' => __DIR__ . '/..' . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n        'vierbergenlars\\\\SemVer\\\\Internal\\\\SemVer' => __DIR__ . '/..' . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php',\n    );\n\n    public static function getInitializer(ClassLoader $loader)\n    {\n        return \\Closure::bind(function () use ($loader) {\n            $loader->prefixLengthsPsr4 = ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16::$prefixLengthsPsr4;\n            $loader->prefixDirsPsr4 = ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16::$prefixDirsPsr4;\n            $loader->prefixesPsr0 = ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16::$prefixesPsr0;\n            $loader->classMap = ComposerStaticInit15ad0a0b334e2ea46dbbf214582f0b16::$classMap;\n\n        }, null, ClassLoader::class);\n    }\n}\n"
  },
  {
    "path": "vendor/composer/installed.json",
    "content": "{\n    \"packages\": [\n        {\n            \"name\": \"cache/adapter-common\",\n            \"version\": \"1.3.0\",\n            \"version_normalized\": \"1.3.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-cache/adapter-common.git\",\n                \"reference\": \"8788309be72aa7be69b88cdc0687549c74a7d479\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-cache/adapter-common/zipball/8788309be72aa7be69b88cdc0687549c74a7d479\",\n                \"reference\": \"8788309be72aa7be69b88cdc0687549c74a7d479\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"cache/tag-interop\": \"^1.0\",\n                \"php\": \">=7.4\",\n                \"psr/cache\": \"^1.0 || ^2.0\",\n                \"psr/log\": \"^1.0 || ^2.0 || ^3.0\",\n                \"psr/simple-cache\": \"^1.0\"\n            },\n            \"require-dev\": {\n                \"cache/integration-tests\": \"^0.17\",\n                \"phpunit/phpunit\": \"^7.5.20 || ^9.5.10\"\n            },\n            \"time\": \"2022-01-15T15:47:19+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.1-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Cache\\\\Adapter\\\\Common\\\\\": \"\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Aaron Scherer\",\n                    \"email\": \"aequasi@gmail.com\",\n                    \"homepage\": \"https://github.com/aequasi\"\n                },\n                {\n                    \"name\": \"Tobias Nyholm\",\n                    \"email\": \"tobias.nyholm@gmail.com\",\n                    \"homepage\": \"https://github.com/nyholm\"\n                }\n            ],\n            \"description\": \"Common classes for PSR-6 adapters\",\n            \"homepage\": \"http://www.php-cache.com/en/latest/\",\n            \"keywords\": [\n                \"cache\",\n                \"psr-6\",\n                \"tag\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-cache/adapter-common/tree/1.3.0\"\n            },\n            \"install-path\": \"../cache/adapter-common\"\n        },\n        {\n            \"name\": \"cache/filesystem-adapter\",\n            \"version\": \"1.2.0\",\n            \"version_normalized\": \"1.2.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-cache/filesystem-adapter.git\",\n                \"reference\": \"f1faaae40aaa696ef899cef6f6888aedb90b419b\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-cache/filesystem-adapter/zipball/f1faaae40aaa696ef899cef6f6888aedb90b419b\",\n                \"reference\": \"f1faaae40aaa696ef899cef6f6888aedb90b419b\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"cache/adapter-common\": \"^1.0\",\n                \"league/flysystem\": \"^1.0\",\n                \"php\": \">=7.4\",\n                \"psr/cache\": \"^1.0 || ^2.0\",\n                \"psr/simple-cache\": \"^1.0\"\n            },\n            \"provide\": {\n                \"psr/cache-implementation\": \"^1.0\",\n                \"psr/simple-cache-implementation\": \"^1.0\"\n            },\n            \"require-dev\": {\n                \"cache/integration-tests\": \"^0.17\",\n                \"phpunit/phpunit\": \"^7.5.20 || ^9.5.10\"\n            },\n            \"time\": \"2022-01-15T15:47:19+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.1-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Cache\\\\Adapter\\\\Filesystem\\\\\": \"\"\n                },\n                \"exclude-from-classmap\": [\n                    \"/Tests/\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Aaron Scherer\",\n                    \"email\": \"aequasi@gmail.com\",\n                    \"homepage\": \"https://github.com/aequasi\"\n                },\n                {\n                    \"name\": \"Tobias Nyholm\",\n                    \"email\": \"tobias.nyholm@gmail.com\",\n                    \"homepage\": \"https://github.com/nyholm\"\n                }\n            ],\n            \"description\": \"A PSR-6 cache implementation using filesystem. This implementation supports tags\",\n            \"homepage\": \"http://www.php-cache.com/en/latest/\",\n            \"keywords\": [\n                \"cache\",\n                \"filesystem\",\n                \"psr-6\",\n                \"tag\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-cache/filesystem-adapter/tree/1.2.0\"\n            },\n            \"install-path\": \"../cache/filesystem-adapter\"\n        },\n        {\n            \"name\": \"cache/tag-interop\",\n            \"version\": \"1.1.0\",\n            \"version_normalized\": \"1.1.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-cache/tag-interop.git\",\n                \"reference\": \"b062b1d735357da50edf8387f7a8696f3027d328\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-cache/tag-interop/zipball/b062b1d735357da50edf8387f7a8696f3027d328\",\n                \"reference\": \"b062b1d735357da50edf8387f7a8696f3027d328\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \"^5.5 || ^7.0 || ^8.0\",\n                \"psr/cache\": \"^1.0 || ^2.0\"\n            },\n            \"time\": \"2021-12-31T10:03:23+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.1-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Cache\\\\TagInterop\\\\\": \"\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Tobias Nyholm\",\n                    \"email\": \"tobias.nyholm@gmail.com\",\n                    \"homepage\": \"https://github.com/nyholm\"\n                },\n                {\n                    \"name\": \"Nicolas Grekas\",\n                    \"email\": \"p@tchwork.com\",\n                    \"homepage\": \"https://github.com/nicolas-grekas\"\n                }\n            ],\n            \"description\": \"Framework interoperable interfaces for tags\",\n            \"homepage\": \"https://www.php-cache.com/en/latest/\",\n            \"keywords\": [\n                \"cache\",\n                \"psr\",\n                \"psr6\",\n                \"tag\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/php-cache/tag-interop/issues\",\n                \"source\": \"https://github.com/php-cache/tag-interop/tree/1.1.0\"\n            },\n            \"install-path\": \"../cache/tag-interop\"\n        },\n        {\n            \"name\": \"clue/socket-raw\",\n            \"version\": \"v1.5.0\",\n            \"version_normalized\": \"1.5.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/clue/php-socket-raw.git\",\n                \"reference\": \"089ffa05fa75bdc4e919aac44bbc435b3ef640ef\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/clue/php-socket-raw/zipball/089ffa05fa75bdc4e919aac44bbc435b3ef640ef\",\n                \"reference\": \"089ffa05fa75bdc4e919aac44bbc435b3ef640ef\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"ext-sockets\": \"*\",\n                \"php\": \">=5.3\"\n            },\n            \"require-dev\": {\n                \"phpunit/phpunit\": \"^9.3 || ^5.7 || ^4.8.35\"\n            },\n            \"time\": \"2020-11-27T13:16:18+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Socket\\\\Raw\\\\\": \"src\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Christian Lück\",\n                    \"email\": \"christian@clue.engineering\"\n                }\n            ],\n            \"description\": \"Simple and lightweight OOP wrapper for PHP's low-level sockets extension (ext-sockets).\",\n            \"homepage\": \"https://github.com/clue/php-socket-raw\",\n            \"keywords\": [\n                \"Socket\",\n                \"client\",\n                \"datagram\",\n                \"dgram\",\n                \"icmp\",\n                \"ipv6\",\n                \"server\",\n                \"stream\",\n                \"tcp\",\n                \"udg\",\n                \"udp\",\n                \"unix\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/clue/php-socket-raw/issues\",\n                \"source\": \"https://github.com/clue/php-socket-raw/tree/v1.5.0\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://clue.engineering/support\",\n                    \"type\": \"custom\"\n                },\n                {\n                    \"url\": \"https://github.com/clue\",\n                    \"type\": \"github\"\n                }\n            ],\n            \"install-path\": \"../clue/socket-raw\"\n        },\n        {\n            \"name\": \"guzzlehttp/guzzle\",\n            \"version\": \"7.4.1\",\n            \"version_normalized\": \"7.4.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/guzzle/guzzle.git\",\n                \"reference\": \"ee0a041b1760e6a53d2a39c8c34115adc2af2c79\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/guzzle/guzzle/zipball/ee0a041b1760e6a53d2a39c8c34115adc2af2c79\",\n                \"reference\": \"ee0a041b1760e6a53d2a39c8c34115adc2af2c79\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"ext-json\": \"*\",\n                \"guzzlehttp/promises\": \"^1.5\",\n                \"guzzlehttp/psr7\": \"^1.8.3 || ^2.1\",\n                \"php\": \"^7.2.5 || ^8.0\",\n                \"psr/http-client\": \"^1.0\",\n                \"symfony/deprecation-contracts\": \"^2.2 || ^3.0\"\n            },\n            \"provide\": {\n                \"psr/http-client-implementation\": \"1.0\"\n            },\n            \"require-dev\": {\n                \"bamarni/composer-bin-plugin\": \"^1.4.1\",\n                \"ext-curl\": \"*\",\n                \"php-http/client-integration-tests\": \"^3.0\",\n                \"phpunit/phpunit\": \"^8.5.5 || ^9.3.5\",\n                \"psr/log\": \"^1.1 || ^2.0 || ^3.0\"\n            },\n            \"suggest\": {\n                \"ext-curl\": \"Required for CURL handler support\",\n                \"ext-intl\": \"Required for Internationalized Domain Name (IDN) support\",\n                \"psr/log\": \"Required for using the Log middleware\"\n            },\n            \"time\": \"2021-12-06T18:43:05+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"7.4-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"src/functions_include.php\"\n                ],\n                \"psr-4\": {\n                    \"GuzzleHttp\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Graham Campbell\",\n                    \"email\": \"hello@gjcampbell.co.uk\",\n                    \"homepage\": \"https://github.com/GrahamCampbell\"\n                },\n                {\n                    \"name\": \"Michael Dowling\",\n                    \"email\": \"mtdowling@gmail.com\",\n                    \"homepage\": \"https://github.com/mtdowling\"\n                },\n                {\n                    \"name\": \"Jeremy Lindblom\",\n                    \"email\": \"jeremeamia@gmail.com\",\n                    \"homepage\": \"https://github.com/jeremeamia\"\n                },\n                {\n                    \"name\": \"George Mponos\",\n                    \"email\": \"gmponos@gmail.com\",\n                    \"homepage\": \"https://github.com/gmponos\"\n                },\n                {\n                    \"name\": \"Tobias Nyholm\",\n                    \"email\": \"tobias.nyholm@gmail.com\",\n                    \"homepage\": \"https://github.com/Nyholm\"\n                },\n                {\n                    \"name\": \"Márk Sági-Kazár\",\n                    \"email\": \"mark.sagikazar@gmail.com\",\n                    \"homepage\": \"https://github.com/sagikazarmark\"\n                },\n                {\n                    \"name\": \"Tobias Schultze\",\n                    \"email\": \"webmaster@tubo-world.de\",\n                    \"homepage\": \"https://github.com/Tobion\"\n                }\n            ],\n            \"description\": \"Guzzle is a PHP HTTP client library\",\n            \"keywords\": [\n                \"client\",\n                \"curl\",\n                \"framework\",\n                \"http\",\n                \"http client\",\n                \"psr-18\",\n                \"psr-7\",\n                \"rest\",\n                \"web service\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/guzzle/guzzle/issues\",\n                \"source\": \"https://github.com/guzzle/guzzle/tree/7.4.1\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://github.com/GrahamCampbell\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://github.com/Nyholm\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../guzzlehttp/guzzle\"\n        },\n        {\n            \"name\": \"guzzlehttp/promises\",\n            \"version\": \"1.5.1\",\n            \"version_normalized\": \"1.5.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/guzzle/promises.git\",\n                \"reference\": \"fe752aedc9fd8fcca3fe7ad05d419d32998a06da\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da\",\n                \"reference\": \"fe752aedc9fd8fcca3fe7ad05d419d32998a06da\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.5\"\n            },\n            \"require-dev\": {\n                \"symfony/phpunit-bridge\": \"^4.4 || ^5.1\"\n            },\n            \"time\": \"2021-10-22T20:56:57+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.5-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"src/functions_include.php\"\n                ],\n                \"psr-4\": {\n                    \"GuzzleHttp\\\\Promise\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Graham Campbell\",\n                    \"email\": \"hello@gjcampbell.co.uk\",\n                    \"homepage\": \"https://github.com/GrahamCampbell\"\n                },\n                {\n                    \"name\": \"Michael Dowling\",\n                    \"email\": \"mtdowling@gmail.com\",\n                    \"homepage\": \"https://github.com/mtdowling\"\n                },\n                {\n                    \"name\": \"Tobias Nyholm\",\n                    \"email\": \"tobias.nyholm@gmail.com\",\n                    \"homepage\": \"https://github.com/Nyholm\"\n                },\n                {\n                    \"name\": \"Tobias Schultze\",\n                    \"email\": \"webmaster@tubo-world.de\",\n                    \"homepage\": \"https://github.com/Tobion\"\n                }\n            ],\n            \"description\": \"Guzzle promises library\",\n            \"keywords\": [\n                \"promise\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/guzzle/promises/issues\",\n                \"source\": \"https://github.com/guzzle/promises/tree/1.5.1\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://github.com/GrahamCampbell\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://github.com/Nyholm\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/guzzlehttp/promises\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../guzzlehttp/promises\"\n        },\n        {\n            \"name\": \"guzzlehttp/psr7\",\n            \"version\": \"2.1.0\",\n            \"version_normalized\": \"2.1.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/guzzle/psr7.git\",\n                \"reference\": \"089edd38f5b8abba6cb01567c2a8aaa47cec4c72\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/guzzle/psr7/zipball/089edd38f5b8abba6cb01567c2a8aaa47cec4c72\",\n                \"reference\": \"089edd38f5b8abba6cb01567c2a8aaa47cec4c72\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \"^7.2.5 || ^8.0\",\n                \"psr/http-factory\": \"^1.0\",\n                \"psr/http-message\": \"^1.0\",\n                \"ralouphie/getallheaders\": \"^3.0\"\n            },\n            \"provide\": {\n                \"psr/http-factory-implementation\": \"1.0\",\n                \"psr/http-message-implementation\": \"1.0\"\n            },\n            \"require-dev\": {\n                \"bamarni/composer-bin-plugin\": \"^1.4.1\",\n                \"http-interop/http-factory-tests\": \"^0.9\",\n                \"phpunit/phpunit\": \"^8.5.8 || ^9.3.10\"\n            },\n            \"suggest\": {\n                \"laminas/laminas-httphandlerrunner\": \"Emit PSR-7 responses\"\n            },\n            \"time\": \"2021-10-06T17:43:30+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"2.1-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"GuzzleHttp\\\\Psr7\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Graham Campbell\",\n                    \"email\": \"hello@gjcampbell.co.uk\",\n                    \"homepage\": \"https://github.com/GrahamCampbell\"\n                },\n                {\n                    \"name\": \"Michael Dowling\",\n                    \"email\": \"mtdowling@gmail.com\",\n                    \"homepage\": \"https://github.com/mtdowling\"\n                },\n                {\n                    \"name\": \"George Mponos\",\n                    \"email\": \"gmponos@gmail.com\",\n                    \"homepage\": \"https://github.com/gmponos\"\n                },\n                {\n                    \"name\": \"Tobias Nyholm\",\n                    \"email\": \"tobias.nyholm@gmail.com\",\n                    \"homepage\": \"https://github.com/Nyholm\"\n                },\n                {\n                    \"name\": \"Márk Sági-Kazár\",\n                    \"email\": \"mark.sagikazar@gmail.com\",\n                    \"homepage\": \"https://github.com/sagikazarmark\"\n                },\n                {\n                    \"name\": \"Tobias Schultze\",\n                    \"email\": \"webmaster@tubo-world.de\",\n                    \"homepage\": \"https://github.com/Tobion\"\n                },\n                {\n                    \"name\": \"Márk Sági-Kazár\",\n                    \"email\": \"mark.sagikazar@gmail.com\",\n                    \"homepage\": \"https://sagikazarmark.hu\"\n                }\n            ],\n            \"description\": \"PSR-7 message implementation that also provides common utility methods\",\n            \"keywords\": [\n                \"http\",\n                \"message\",\n                \"psr-7\",\n                \"request\",\n                \"response\",\n                \"stream\",\n                \"uri\",\n                \"url\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/guzzle/psr7/issues\",\n                \"source\": \"https://github.com/guzzle/psr7/tree/2.1.0\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://github.com/GrahamCampbell\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://github.com/Nyholm\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/guzzlehttp/psr7\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../guzzlehttp/psr7\"\n        },\n        {\n            \"name\": \"jaeger/g-http\",\n            \"version\": \"V1.7.2\",\n            \"version_normalized\": \"1.7.2.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/jae-jae/GHttp.git\",\n                \"reference\": \"82585ddd5e2c6651e37ab1d8166efcdbb6b293d4\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/jae-jae/GHttp/zipball/82585ddd5e2c6651e37ab1d8166efcdbb6b293d4\",\n                \"reference\": \"82585ddd5e2c6651e37ab1d8166efcdbb6b293d4\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"cache/filesystem-adapter\": \"^1\",\n                \"guzzlehttp/guzzle\": \"^6.0 | ^7.0\"\n            },\n            \"time\": \"2021-08-08T04:59:44+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Jaeger\\\\\": \"src\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Jaeger\",\n                    \"email\": \"JaegerCode@gmail.com\"\n                }\n            ],\n            \"description\": \"Simple Http client base on GuzzleHttp\",\n            \"support\": {\n                \"issues\": \"https://github.com/jae-jae/GHttp/issues\",\n                \"source\": \"https://github.com/jae-jae/GHttp/tree/V1.7.2\"\n            },\n            \"install-path\": \"../jaeger/g-http\"\n        },\n        {\n            \"name\": \"jaeger/phpquery-single\",\n            \"version\": \"1.0.1\",\n            \"version_normalized\": \"1.0.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/jae-jae/phpQuery-single.git\",\n                \"reference\": \"fb80b4a0e5a337438d26e061ec3fb725c9f2a116\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/jae-jae/phpQuery-single/zipball/fb80b4a0e5a337438d26e061ec3fb725c9f2a116\",\n                \"reference\": \"fb80b4a0e5a337438d26e061ec3fb725c9f2a116\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.3.0\"\n            },\n            \"time\": \"2019-11-05T01:50:34+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"classmap\": [\n                    \"phpQuery.php\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Tobiasz Cudnik\",\n                    \"email\": \"tobiasz.cudnik@gmail.com\",\n                    \"homepage\": \"https://github.com/TobiaszCudnik\",\n                    \"role\": \"Developer\"\n                },\n                {\n                    \"name\": \"Jaeger\",\n                    \"role\": \"Packager\"\n                }\n            ],\n            \"description\": \"phpQuery单文件版本，是Querylist的依赖(http://querylist.cc/)，phpQuery项目主页:http://code.google.com/p/phpquery/\",\n            \"homepage\": \"http://code.google.com/p/phpquery/\",\n            \"support\": {\n                \"issues\": \"https://github.com/jae-jae/phpQuery-single/issues\",\n                \"source\": \"https://github.com/jae-jae/phpQuery-single/tree/master\"\n            },\n            \"install-path\": \"../jaeger/phpquery-single\"\n        },\n        {\n            \"name\": \"jaeger/querylist\",\n            \"version\": \"V4.2.8\",\n            \"version_normalized\": \"4.2.8.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/jae-jae/QueryList.git\",\n                \"reference\": \"39dc0ca9c668bec7a793e20472ccd7d26ef89ea4\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/jae-jae/QueryList/zipball/39dc0ca9c668bec7a793e20472ccd7d26ef89ea4\",\n                \"reference\": \"39dc0ca9c668bec7a793e20472ccd7d26ef89ea4\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"ext-dom\": \"*\",\n                \"jaeger/g-http\": \"^1.1\",\n                \"jaeger/phpquery-single\": \"^1\",\n                \"php\": \">=7.1\",\n                \"tightenco/collect\": \">5.0\"\n            },\n            \"require-dev\": {\n                \"phpunit/phpunit\": \"^8.5\",\n                \"symfony/var-dumper\": \"^3.3\"\n            },\n            \"time\": \"2021-07-05T06:07:58+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"QL\\\\\": \"src\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Jaeger\",\n                    \"email\": \"JaegerCode@gmail.com\"\n                }\n            ],\n            \"description\": \"Simple, elegant, extensible PHP Web Scraper (crawler/spider),Use the css3 dom selector,Based on phpQuery! 简洁、优雅、可扩展的PHP采集工具(爬虫)，基于phpQuery。\",\n            \"homepage\": \"http://querylist.cc\",\n            \"keywords\": [\n                \"QueryList\",\n                \"phpQuery\",\n                \"spider\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/jae-jae/QueryList/issues\",\n                \"source\": \"https://github.com/jae-jae/QueryList/tree/V4.2.8\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://opencollective.com/querylist\",\n                    \"type\": \"open_collective\"\n                }\n            ],\n            \"install-path\": \"../jaeger/querylist\"\n        },\n        {\n            \"name\": \"jaeger/querylist-puppeteer\",\n            \"version\": \"4.0.0\",\n            \"version_normalized\": \"4.0.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/jae-jae/QueryList-Puppeteer.git\",\n                \"reference\": \"c6bd5acc4c95022bea92ba1308841b863eab2cf0\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/jae-jae/QueryList-Puppeteer/zipball/c6bd5acc4c95022bea92ba1308841b863eab2cf0\",\n                \"reference\": \"c6bd5acc4c95022bea92ba1308841b863eab2cf0\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"nesk/puphpeteer\": \"^1.4\",\n                \"php\": \">=7.1\"\n            },\n            \"require-dev\": {\n                \"jaeger/querylist\": \"dev-master\"\n            },\n            \"time\": \"2019-01-15T10:18:49+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"QL\\\\Ext\\\\\": \"\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Jaeger\",\n                    \"email\": \"JaegerCode@gmail.com\"\n                }\n            ],\n            \"description\": \"QueryList Plugin: Use Puppeteer to crawl Javascript dynamically rendered pages.(Headless Chrome ) 使用Puppeteer采集JavaScript动态渲染的页面\",\n            \"support\": {\n                \"issues\": \"https://github.com/jae-jae/QueryList-Puppeteer/issues\",\n                \"source\": \"https://github.com/jae-jae/QueryList-Puppeteer/tree/4.0.0\"\n            },\n            \"install-path\": \"../jaeger/querylist-puppeteer\"\n        },\n        {\n            \"name\": \"league/flysystem\",\n            \"version\": \"1.1.9\",\n            \"version_normalized\": \"1.1.9.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/thephpleague/flysystem.git\",\n                \"reference\": \"094defdb4a7001845300334e7c1ee2335925ef99\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/thephpleague/flysystem/zipball/094defdb4a7001845300334e7c1ee2335925ef99\",\n                \"reference\": \"094defdb4a7001845300334e7c1ee2335925ef99\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"ext-fileinfo\": \"*\",\n                \"league/mime-type-detection\": \"^1.3\",\n                \"php\": \"^7.2.5 || ^8.0\"\n            },\n            \"conflict\": {\n                \"league/flysystem-sftp\": \"<1.0.6\"\n            },\n            \"require-dev\": {\n                \"phpspec/prophecy\": \"^1.11.1\",\n                \"phpunit/phpunit\": \"^8.5.8\"\n            },\n            \"suggest\": {\n                \"ext-ftp\": \"Allows you to use FTP server storage\",\n                \"ext-openssl\": \"Allows you to use FTPS server storage\",\n                \"league/flysystem-aws-s3-v2\": \"Allows you to use S3 storage with AWS SDK v2\",\n                \"league/flysystem-aws-s3-v3\": \"Allows you to use S3 storage with AWS SDK v3\",\n                \"league/flysystem-azure\": \"Allows you to use Windows Azure Blob storage\",\n                \"league/flysystem-cached-adapter\": \"Flysystem adapter decorator for metadata caching\",\n                \"league/flysystem-eventable-filesystem\": \"Allows you to use EventableFilesystem\",\n                \"league/flysystem-rackspace\": \"Allows you to use Rackspace Cloud Files\",\n                \"league/flysystem-sftp\": \"Allows you to use SFTP server storage via phpseclib\",\n                \"league/flysystem-webdav\": \"Allows you to use WebDAV storage\",\n                \"league/flysystem-ziparchive\": \"Allows you to use ZipArchive adapter\",\n                \"spatie/flysystem-dropbox\": \"Allows you to use Dropbox storage\",\n                \"srmklive/flysystem-dropbox-v2\": \"Allows you to use Dropbox storage for PHP 5 applications\"\n            },\n            \"time\": \"2021-12-09T09:40:50+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.1-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"League\\\\Flysystem\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Frank de Jonge\",\n                    \"email\": \"info@frenky.net\"\n                }\n            ],\n            \"description\": \"Filesystem abstraction: Many filesystems, one API.\",\n            \"keywords\": [\n                \"Cloud Files\",\n                \"WebDAV\",\n                \"abstraction\",\n                \"aws\",\n                \"cloud\",\n                \"copy.com\",\n                \"dropbox\",\n                \"file systems\",\n                \"files\",\n                \"filesystem\",\n                \"filesystems\",\n                \"ftp\",\n                \"rackspace\",\n                \"remote\",\n                \"s3\",\n                \"sftp\",\n                \"storage\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/thephpleague/flysystem/issues\",\n                \"source\": \"https://github.com/thephpleague/flysystem/tree/1.1.9\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://offset.earth/frankdejonge\",\n                    \"type\": \"other\"\n                }\n            ],\n            \"install-path\": \"../league/flysystem\"\n        },\n        {\n            \"name\": \"league/mime-type-detection\",\n            \"version\": \"1.10.0\",\n            \"version_normalized\": \"1.10.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/thephpleague/mime-type-detection.git\",\n                \"reference\": \"3e4a35d756eedc67096f30240a68a3149120dae7\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/thephpleague/mime-type-detection/zipball/3e4a35d756eedc67096f30240a68a3149120dae7\",\n                \"reference\": \"3e4a35d756eedc67096f30240a68a3149120dae7\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"ext-fileinfo\": \"*\",\n                \"php\": \"^7.2 || ^8.0\"\n            },\n            \"require-dev\": {\n                \"friendsofphp/php-cs-fixer\": \"^3.2\",\n                \"phpstan/phpstan\": \"^0.12.68\",\n                \"phpunit/phpunit\": \"^8.5.8 || ^9.3\"\n            },\n            \"time\": \"2022-04-11T12:49:04+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"League\\\\MimeTypeDetection\\\\\": \"src\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Frank de Jonge\",\n                    \"email\": \"info@frankdejonge.nl\"\n                }\n            ],\n            \"description\": \"Mime-type detection for Flysystem\",\n            \"support\": {\n                \"issues\": \"https://github.com/thephpleague/mime-type-detection/issues\",\n                \"source\": \"https://github.com/thephpleague/mime-type-detection/tree/1.10.0\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://github.com/frankdejonge\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/league/flysystem\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../league/mime-type-detection\"\n        },\n        {\n            \"name\": \"nesk/puphpeteer\",\n            \"version\": \"1.6.0\",\n            \"version_normalized\": \"1.6.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/nesk/puphpeteer.git\",\n                \"reference\": \"21adf25d320f32b005cb3e2f9026616566015fcc\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/nesk/puphpeteer/zipball/21adf25d320f32b005cb3e2f9026616566015fcc\",\n                \"reference\": \"21adf25d320f32b005cb3e2f9026616566015fcc\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"nesk/rialto\": \"^1.2.0\",\n                \"php\": \">=7.1\",\n                \"psr/log\": \"^1.0\",\n                \"vierbergenlars/php-semver\": \"^3.0.2\"\n            },\n            \"require-dev\": {\n                \"codedungeon/phpunit-result-printer\": \">=0.6 <1.0\",\n                \"monolog/monolog\": \"^1.23\",\n                \"phpunit/phpunit\": \"^6.5|^7.0\",\n                \"symfony/process\": \"^4.0\"\n            },\n            \"time\": \"2019-06-24T11:12:21+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Nesk\\\\Puphpeteer\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Johann Pardanaud\",\n                    \"email\": \"pardanaud.j@gmail.com\"\n                }\n            ],\n            \"description\": \"A Puppeteer bridge for PHP, supporting the entire API.\",\n            \"keywords\": [\n                \"automation\",\n                \"developer-tools\",\n                \"headless-chrome\",\n                \"php\",\n                \"puppeteer\",\n                \"testing\",\n                \"web\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/nesk/puphpeteer/issues\",\n                \"source\": \"https://github.com/nesk/puphpeteer/tree/1.6.0\"\n            },\n            \"install-path\": \"../nesk/puphpeteer\"\n        },\n        {\n            \"name\": \"nesk/rialto\",\n            \"version\": \"1.4.0\",\n            \"version_normalized\": \"1.4.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/nesk/rialto.git\",\n                \"reference\": \"a3db615d845cca42135fa1e271b323ffe904b83c\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/nesk/rialto/zipball/a3db615d845cca42135fa1e271b323ffe904b83c\",\n                \"reference\": \"a3db615d845cca42135fa1e271b323ffe904b83c\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"clue/socket-raw\": \"^1.2\",\n                \"php\": \">=7.1\",\n                \"psr/log\": \"^1.0\",\n                \"symfony/process\": \"^3.3|^4.0|^5.0\"\n            },\n            \"require-dev\": {\n                \"codedungeon/phpunit-result-printer\": \">=0.6 <1.0\",\n                \"monolog/monolog\": \"^1.23\",\n                \"phpunit/phpunit\": \"^6.5|^7.0\"\n            },\n            \"suggest\": {\n                \"ext-weakref\": \"Required to run all the tests\"\n            },\n            \"time\": \"2020-04-12T13:11:08+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Nesk\\\\Rialto\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Johann Pardanaud\",\n                    \"email\": \"pardanaud.j@gmail.com\"\n                }\n            ],\n            \"description\": \"Manage Node resources from PHP\",\n            \"keywords\": [\n                \"Bridge\",\n                \"Socket\",\n                \"communication\",\n                \"node\",\n                \"php\",\n                \"wrapper\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/nesk/rialto/issues\",\n                \"source\": \"https://github.com/nesk/rialto/tree/1.4.0\"\n            },\n            \"install-path\": \"../nesk/rialto\"\n        },\n        {\n            \"name\": \"psr/cache\",\n            \"version\": \"2.0.0\",\n            \"version_normalized\": \"2.0.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-fig/cache.git\",\n                \"reference\": \"213f9dbc5b9bfbc4f8db86d2838dc968752ce13b\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b\",\n                \"reference\": \"213f9dbc5b9bfbc4f8db86d2838dc968752ce13b\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=8.0.0\"\n            },\n            \"time\": \"2021-02-03T23:23:37+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.0.x-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Psr\\\\Cache\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"PHP-FIG\",\n                    \"homepage\": \"https://www.php-fig.org/\"\n                }\n            ],\n            \"description\": \"Common interface for caching libraries\",\n            \"keywords\": [\n                \"cache\",\n                \"psr\",\n                \"psr-6\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-fig/cache/tree/2.0.0\"\n            },\n            \"install-path\": \"../psr/cache\"\n        },\n        {\n            \"name\": \"psr/http-client\",\n            \"version\": \"1.0.1\",\n            \"version_normalized\": \"1.0.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-fig/http-client.git\",\n                \"reference\": \"2dfb5f6c5eff0e91e20e913f8c5452ed95b86621\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621\",\n                \"reference\": \"2dfb5f6c5eff0e91e20e913f8c5452ed95b86621\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \"^7.0 || ^8.0\",\n                \"psr/http-message\": \"^1.0\"\n            },\n            \"time\": \"2020-06-29T06:28:15+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.0.x-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Psr\\\\Http\\\\Client\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"PHP-FIG\",\n                    \"homepage\": \"http://www.php-fig.org/\"\n                }\n            ],\n            \"description\": \"Common interface for HTTP clients\",\n            \"homepage\": \"https://github.com/php-fig/http-client\",\n            \"keywords\": [\n                \"http\",\n                \"http-client\",\n                \"psr\",\n                \"psr-18\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-fig/http-client/tree/master\"\n            },\n            \"install-path\": \"../psr/http-client\"\n        },\n        {\n            \"name\": \"psr/http-factory\",\n            \"version\": \"1.0.1\",\n            \"version_normalized\": \"1.0.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-fig/http-factory.git\",\n                \"reference\": \"12ac7fcd07e5b077433f5f2bee95b3a771bf61be\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be\",\n                \"reference\": \"12ac7fcd07e5b077433f5f2bee95b3a771bf61be\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=7.0.0\",\n                \"psr/http-message\": \"^1.0\"\n            },\n            \"time\": \"2019-04-30T12:38:16+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.0.x-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Psr\\\\Http\\\\Message\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"PHP-FIG\",\n                    \"homepage\": \"http://www.php-fig.org/\"\n                }\n            ],\n            \"description\": \"Common interfaces for PSR-7 HTTP message factories\",\n            \"keywords\": [\n                \"factory\",\n                \"http\",\n                \"message\",\n                \"psr\",\n                \"psr-17\",\n                \"psr-7\",\n                \"request\",\n                \"response\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-fig/http-factory/tree/master\"\n            },\n            \"install-path\": \"../psr/http-factory\"\n        },\n        {\n            \"name\": \"psr/http-message\",\n            \"version\": \"1.0.1\",\n            \"version_normalized\": \"1.0.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-fig/http-message.git\",\n                \"reference\": \"f6561bf28d520154e4b0ec72be95418abe6d9363\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363\",\n                \"reference\": \"f6561bf28d520154e4b0ec72be95418abe6d9363\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.3.0\"\n            },\n            \"time\": \"2016-08-06T14:39:51+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.0.x-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Psr\\\\Http\\\\Message\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"PHP-FIG\",\n                    \"homepage\": \"http://www.php-fig.org/\"\n                }\n            ],\n            \"description\": \"Common interface for HTTP messages\",\n            \"homepage\": \"https://github.com/php-fig/http-message\",\n            \"keywords\": [\n                \"http\",\n                \"http-message\",\n                \"psr\",\n                \"psr-7\",\n                \"request\",\n                \"response\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-fig/http-message/tree/master\"\n            },\n            \"install-path\": \"../psr/http-message\"\n        },\n        {\n            \"name\": \"psr/log\",\n            \"version\": \"1.1.4\",\n            \"version_normalized\": \"1.1.4.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-fig/log.git\",\n                \"reference\": \"d49695b909c3b7628b6289db5479a1c204601f11\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11\",\n                \"reference\": \"d49695b909c3b7628b6289db5479a1c204601f11\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.3.0\"\n            },\n            \"time\": \"2021-05-03T11:20:27+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.1.x-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Psr\\\\Log\\\\\": \"Psr/Log/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"PHP-FIG\",\n                    \"homepage\": \"https://www.php-fig.org/\"\n                }\n            ],\n            \"description\": \"Common interface for logging libraries\",\n            \"homepage\": \"https://github.com/php-fig/log\",\n            \"keywords\": [\n                \"log\",\n                \"psr\",\n                \"psr-3\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-fig/log/tree/1.1.4\"\n            },\n            \"install-path\": \"../psr/log\"\n        },\n        {\n            \"name\": \"psr/simple-cache\",\n            \"version\": \"1.0.1\",\n            \"version_normalized\": \"1.0.1.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/php-fig/simple-cache.git\",\n                \"reference\": \"408d5eafb83c57f6365a3ca330ff23aa4a5fa39b\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b\",\n                \"reference\": \"408d5eafb83c57f6365a3ca330ff23aa4a5fa39b\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.3.0\"\n            },\n            \"time\": \"2017-10-23T01:57:42+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-master\": \"1.0.x-dev\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Psr\\\\SimpleCache\\\\\": \"src/\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"PHP-FIG\",\n                    \"homepage\": \"http://www.php-fig.org/\"\n                }\n            ],\n            \"description\": \"Common interfaces for simple caching\",\n            \"keywords\": [\n                \"cache\",\n                \"caching\",\n                \"psr\",\n                \"psr-16\",\n                \"simple-cache\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/php-fig/simple-cache/tree/master\"\n            },\n            \"install-path\": \"../psr/simple-cache\"\n        },\n        {\n            \"name\": \"ralouphie/getallheaders\",\n            \"version\": \"3.0.3\",\n            \"version_normalized\": \"3.0.3.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/ralouphie/getallheaders.git\",\n                \"reference\": \"120b605dfeb996808c31b6477290a714d356e822\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822\",\n                \"reference\": \"120b605dfeb996808c31b6477290a714d356e822\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.6\"\n            },\n            \"require-dev\": {\n                \"php-coveralls/php-coveralls\": \"^2.1\",\n                \"phpunit/phpunit\": \"^5 || ^6.5\"\n            },\n            \"time\": \"2019-03-08T08:55:37+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"src/getallheaders.php\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Ralph Khattar\",\n                    \"email\": \"ralph.khattar@gmail.com\"\n                }\n            ],\n            \"description\": \"A polyfill for getallheaders.\",\n            \"support\": {\n                \"issues\": \"https://github.com/ralouphie/getallheaders/issues\",\n                \"source\": \"https://github.com/ralouphie/getallheaders/tree/develop\"\n            },\n            \"install-path\": \"../ralouphie/getallheaders\"\n        },\n        {\n            \"name\": \"symfony/deprecation-contracts\",\n            \"version\": \"v3.0.0\",\n            \"version_normalized\": \"3.0.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/symfony/deprecation-contracts.git\",\n                \"reference\": \"c726b64c1ccfe2896cb7df2e1331c357ad1c8ced\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced\",\n                \"reference\": \"c726b64c1ccfe2896cb7df2e1331c357ad1c8ced\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=8.0.2\"\n            },\n            \"time\": \"2021-11-01T23:48:49+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-main\": \"3.0-dev\"\n                },\n                \"thanks\": {\n                    \"name\": \"symfony/contracts\",\n                    \"url\": \"https://github.com/symfony/contracts\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"function.php\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Nicolas Grekas\",\n                    \"email\": \"p@tchwork.com\"\n                },\n                {\n                    \"name\": \"Symfony Community\",\n                    \"homepage\": \"https://symfony.com/contributors\"\n                }\n            ],\n            \"description\": \"A generic function and convention to trigger deprecation notices\",\n            \"homepage\": \"https://symfony.com\",\n            \"support\": {\n                \"source\": \"https://github.com/symfony/deprecation-contracts/tree/v3.0.0\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://symfony.com/sponsor\",\n                    \"type\": \"custom\"\n                },\n                {\n                    \"url\": \"https://github.com/fabpot\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/symfony/symfony\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../symfony/deprecation-contracts\"\n        },\n        {\n            \"name\": \"symfony/polyfill-mbstring\",\n            \"version\": \"v1.25.0\",\n            \"version_normalized\": \"1.25.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/symfony/polyfill-mbstring.git\",\n                \"reference\": \"0abb51d2f102e00a4eefcf46ba7fec406d245825\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825\",\n                \"reference\": \"0abb51d2f102e00a4eefcf46ba7fec406d245825\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=7.1\"\n            },\n            \"provide\": {\n                \"ext-mbstring\": \"*\"\n            },\n            \"suggest\": {\n                \"ext-mbstring\": \"For best performance\"\n            },\n            \"time\": \"2021-11-30T18:21:41+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-main\": \"1.23-dev\"\n                },\n                \"thanks\": {\n                    \"name\": \"symfony/polyfill\",\n                    \"url\": \"https://github.com/symfony/polyfill\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"bootstrap.php\"\n                ],\n                \"psr-4\": {\n                    \"Symfony\\\\Polyfill\\\\Mbstring\\\\\": \"\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Nicolas Grekas\",\n                    \"email\": \"p@tchwork.com\"\n                },\n                {\n                    \"name\": \"Symfony Community\",\n                    \"homepage\": \"https://symfony.com/contributors\"\n                }\n            ],\n            \"description\": \"Symfony polyfill for the Mbstring extension\",\n            \"homepage\": \"https://symfony.com\",\n            \"keywords\": [\n                \"compatibility\",\n                \"mbstring\",\n                \"polyfill\",\n                \"portable\",\n                \"shim\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/symfony/polyfill-mbstring/tree/v1.25.0\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://symfony.com/sponsor\",\n                    \"type\": \"custom\"\n                },\n                {\n                    \"url\": \"https://github.com/fabpot\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/symfony/symfony\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../symfony/polyfill-mbstring\"\n        },\n        {\n            \"name\": \"symfony/polyfill-php80\",\n            \"version\": \"v1.25.0\",\n            \"version_normalized\": \"1.25.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/symfony/polyfill-php80.git\",\n                \"reference\": \"4407588e0d3f1f52efb65fbe92babe41f37fe50c\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c\",\n                \"reference\": \"4407588e0d3f1f52efb65fbe92babe41f37fe50c\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=7.1\"\n            },\n            \"time\": \"2022-03-04T08:16:47+00:00\",\n            \"type\": \"library\",\n            \"extra\": {\n                \"branch-alias\": {\n                    \"dev-main\": \"1.23-dev\"\n                },\n                \"thanks\": {\n                    \"name\": \"symfony/polyfill\",\n                    \"url\": \"https://github.com/symfony/polyfill\"\n                }\n            },\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"bootstrap.php\"\n                ],\n                \"psr-4\": {\n                    \"Symfony\\\\Polyfill\\\\Php80\\\\\": \"\"\n                },\n                \"classmap\": [\n                    \"Resources/stubs\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Ion Bazan\",\n                    \"email\": \"ion.bazan@gmail.com\"\n                },\n                {\n                    \"name\": \"Nicolas Grekas\",\n                    \"email\": \"p@tchwork.com\"\n                },\n                {\n                    \"name\": \"Symfony Community\",\n                    \"homepage\": \"https://symfony.com/contributors\"\n                }\n            ],\n            \"description\": \"Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions\",\n            \"homepage\": \"https://symfony.com\",\n            \"keywords\": [\n                \"compatibility\",\n                \"polyfill\",\n                \"portable\",\n                \"shim\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/symfony/polyfill-php80/tree/v1.25.0\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://symfony.com/sponsor\",\n                    \"type\": \"custom\"\n                },\n                {\n                    \"url\": \"https://github.com/fabpot\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/symfony/symfony\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../symfony/polyfill-php80\"\n        },\n        {\n            \"name\": \"symfony/process\",\n            \"version\": \"v5.4.7\",\n            \"version_normalized\": \"5.4.7.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/symfony/process.git\",\n                \"reference\": \"38a44b2517b470a436e1c944bf9b9ba3961137fb\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/symfony/process/zipball/38a44b2517b470a436e1c944bf9b9ba3961137fb\",\n                \"reference\": \"38a44b2517b470a436e1c944bf9b9ba3961137fb\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=7.2.5\",\n                \"symfony/polyfill-php80\": \"^1.16\"\n            },\n            \"time\": \"2022-03-18T16:18:52+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-4\": {\n                    \"Symfony\\\\Component\\\\Process\\\\\": \"\"\n                },\n                \"exclude-from-classmap\": [\n                    \"/Tests/\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Fabien Potencier\",\n                    \"email\": \"fabien@symfony.com\"\n                },\n                {\n                    \"name\": \"Symfony Community\",\n                    \"homepage\": \"https://symfony.com/contributors\"\n                }\n            ],\n            \"description\": \"Executes commands in sub-processes\",\n            \"homepage\": \"https://symfony.com\",\n            \"support\": {\n                \"source\": \"https://github.com/symfony/process/tree/v5.4.7\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://symfony.com/sponsor\",\n                    \"type\": \"custom\"\n                },\n                {\n                    \"url\": \"https://github.com/fabpot\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/symfony/symfony\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../symfony/process\"\n        },\n        {\n            \"name\": \"symfony/var-dumper\",\n            \"version\": \"v5.4.6\",\n            \"version_normalized\": \"5.4.6.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/symfony/var-dumper.git\",\n                \"reference\": \"294e9da6e2e0dd404e983daa5aa74253d92c05d0\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/symfony/var-dumper/zipball/294e9da6e2e0dd404e983daa5aa74253d92c05d0\",\n                \"reference\": \"294e9da6e2e0dd404e983daa5aa74253d92c05d0\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=7.2.5\",\n                \"symfony/polyfill-mbstring\": \"~1.0\",\n                \"symfony/polyfill-php80\": \"^1.16\"\n            },\n            \"conflict\": {\n                \"phpunit/phpunit\": \"<5.4.3\",\n                \"symfony/console\": \"<4.4\"\n            },\n            \"require-dev\": {\n                \"ext-iconv\": \"*\",\n                \"symfony/console\": \"^4.4|^5.0|^6.0\",\n                \"symfony/process\": \"^4.4|^5.0|^6.0\",\n                \"symfony/uid\": \"^5.1|^6.0\",\n                \"twig/twig\": \"^2.13|^3.0.4\"\n            },\n            \"suggest\": {\n                \"ext-iconv\": \"To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).\",\n                \"ext-intl\": \"To show region name in time zone dump\",\n                \"symfony/console\": \"To use the ServerDumpCommand and/or the bin/var-dump-server script\"\n            },\n            \"time\": \"2022-03-02T12:42:23+00:00\",\n            \"bin\": [\n                \"Resources/bin/var-dump-server\"\n            ],\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"Resources/functions/dump.php\"\n                ],\n                \"psr-4\": {\n                    \"Symfony\\\\Component\\\\VarDumper\\\\\": \"\"\n                },\n                \"exclude-from-classmap\": [\n                    \"/Tests/\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Nicolas Grekas\",\n                    \"email\": \"p@tchwork.com\"\n                },\n                {\n                    \"name\": \"Symfony Community\",\n                    \"homepage\": \"https://symfony.com/contributors\"\n                }\n            ],\n            \"description\": \"Provides mechanisms for walking through any arbitrary PHP variable\",\n            \"homepage\": \"https://symfony.com\",\n            \"keywords\": [\n                \"debug\",\n                \"dump\"\n            ],\n            \"support\": {\n                \"source\": \"https://github.com/symfony/var-dumper/tree/v5.4.6\"\n            },\n            \"funding\": [\n                {\n                    \"url\": \"https://symfony.com/sponsor\",\n                    \"type\": \"custom\"\n                },\n                {\n                    \"url\": \"https://github.com/fabpot\",\n                    \"type\": \"github\"\n                },\n                {\n                    \"url\": \"https://tidelift.com/funding/github/packagist/symfony/symfony\",\n                    \"type\": \"tidelift\"\n                }\n            ],\n            \"install-path\": \"../symfony/var-dumper\"\n        },\n        {\n            \"name\": \"tightenco/collect\",\n            \"version\": \"8.78.0\",\n            \"version_normalized\": \"8.78.0.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/tighten/collect.git\",\n                \"reference\": \"3a42ca9b730a88e942fe05180d4f15e045464e40\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/tighten/collect/zipball/3a42ca9b730a88e942fe05180d4f15e045464e40\",\n                \"reference\": \"3a42ca9b730a88e942fe05180d4f15e045464e40\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \"^7.2|^8.0\",\n                \"symfony/var-dumper\": \"^3.4 || ^4.0 || ^5.0 || ^6.0\"\n            },\n            \"require-dev\": {\n                \"mockery/mockery\": \"^1.0\",\n                \"nesbot/carbon\": \"^2.23.0\",\n                \"phpunit/phpunit\": \"^8.3\"\n            },\n            \"time\": \"2022-01-04T21:38:24+00:00\",\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"files\": [\n                    \"src/Collect/Support/helpers.php\",\n                    \"src/Collect/Support/alias.php\"\n                ],\n                \"psr-4\": {\n                    \"Tightenco\\\\Collect\\\\\": \"src/Collect\"\n                }\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Taylor Otwell\",\n                    \"email\": \"taylorotwell@gmail.com\"\n                }\n            ],\n            \"description\": \"Collect - Illuminate Collections as a separate package.\",\n            \"keywords\": [\n                \"collection\",\n                \"laravel\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/tighten/collect/issues\",\n                \"source\": \"https://github.com/tighten/collect/tree/8.78.0\"\n            },\n            \"install-path\": \"../tightenco/collect\"\n        },\n        {\n            \"name\": \"vierbergenlars/php-semver\",\n            \"version\": \"3.0.2\",\n            \"version_normalized\": \"3.0.2.0\",\n            \"source\": {\n                \"type\": \"git\",\n                \"url\": \"https://github.com/vierbergenlars/php-semver.git\",\n                \"reference\": \"be22b86be4c1133acc42fd1685276792024af5f9\"\n            },\n            \"dist\": {\n                \"type\": \"zip\",\n                \"url\": \"https://api.github.com/repos/vierbergenlars/php-semver/zipball/be22b86be4c1133acc42fd1685276792024af5f9\",\n                \"reference\": \"be22b86be4c1133acc42fd1685276792024af5f9\",\n                \"shasum\": \"\",\n                \"mirrors\": [\n                    {\n                        \"url\": \"https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%\",\n                        \"preferred\": true\n                    }\n                ]\n            },\n            \"require\": {\n                \"php\": \">=5.3.0\"\n            },\n            \"require-dev\": {\n                \"phpunit/phpunit\": \"~4\"\n            },\n            \"time\": \"2017-07-11T09:53:59+00:00\",\n            \"bin\": [\n                \"bin/semver\",\n                \"bin/update-versions\"\n            ],\n            \"type\": \"library\",\n            \"installation-source\": \"dist\",\n            \"autoload\": {\n                \"psr-0\": {\n                    \"vierbergenlars\\\\LibJs\\\\\": \"src/\",\n                    \"vierbergenlars\\\\SemVer\\\\\": \"src/\"\n                },\n                \"classmap\": [\n                    \"src/vierbergenlars/SemVer/internal.php\"\n                ]\n            },\n            \"notification-url\": \"https://packagist.org/downloads/\",\n            \"license\": [\n                \"MIT\"\n            ],\n            \"authors\": [\n                {\n                    \"name\": \"Lars Vierbergen\",\n                    \"email\": \"vierbergenlars@gmail.com\"\n                }\n            ],\n            \"description\": \"The Semantic Versioner for PHP\",\n            \"keywords\": [\n                \"semantic\",\n                \"semver\",\n                \"versioning\"\n            ],\n            \"support\": {\n                \"issues\": \"https://github.com/vierbergenlars/php-semver/issues\",\n                \"source\": \"https://github.com/vierbergenlars/php-semver/tree/master\"\n            },\n            \"install-path\": \"../vierbergenlars/php-semver\"\n        }\n    ],\n    \"dev\": true,\n    \"dev-package-names\": []\n}\n"
  },
  {
    "path": "vendor/composer/installed.php",
    "content": "<?php return array(\n    'root' => array(\n        'pretty_version' => 'dev-master',\n        'version' => 'dev-master',\n        'type' => 'library',\n        'install_path' => __DIR__ . '/../../',\n        'aliases' => array(),\n        'reference' => 'ba87124f21aab3e4b120b9d18dccc3397bc50b4b',\n        'name' => '__root__',\n        'dev' => true,\n    ),\n    'versions' => array(\n        '__root__' => array(\n            'pretty_version' => 'dev-master',\n            'version' => 'dev-master',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../../',\n            'aliases' => array(),\n            'reference' => 'ba87124f21aab3e4b120b9d18dccc3397bc50b4b',\n            'dev_requirement' => false,\n        ),\n        'cache/adapter-common' => array(\n            'pretty_version' => '1.3.0',\n            'version' => '1.3.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../cache/adapter-common',\n            'aliases' => array(),\n            'reference' => '8788309be72aa7be69b88cdc0687549c74a7d479',\n            'dev_requirement' => false,\n        ),\n        'cache/filesystem-adapter' => array(\n            'pretty_version' => '1.2.0',\n            'version' => '1.2.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../cache/filesystem-adapter',\n            'aliases' => array(),\n            'reference' => 'f1faaae40aaa696ef899cef6f6888aedb90b419b',\n            'dev_requirement' => false,\n        ),\n        'cache/tag-interop' => array(\n            'pretty_version' => '1.1.0',\n            'version' => '1.1.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../cache/tag-interop',\n            'aliases' => array(),\n            'reference' => 'b062b1d735357da50edf8387f7a8696f3027d328',\n            'dev_requirement' => false,\n        ),\n        'clue/socket-raw' => array(\n            'pretty_version' => 'v1.5.0',\n            'version' => '1.5.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../clue/socket-raw',\n            'aliases' => array(),\n            'reference' => '089ffa05fa75bdc4e919aac44bbc435b3ef640ef',\n            'dev_requirement' => false,\n        ),\n        'guzzlehttp/guzzle' => array(\n            'pretty_version' => '7.4.1',\n            'version' => '7.4.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../guzzlehttp/guzzle',\n            'aliases' => array(),\n            'reference' => 'ee0a041b1760e6a53d2a39c8c34115adc2af2c79',\n            'dev_requirement' => false,\n        ),\n        'guzzlehttp/promises' => array(\n            'pretty_version' => '1.5.1',\n            'version' => '1.5.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../guzzlehttp/promises',\n            'aliases' => array(),\n            'reference' => 'fe752aedc9fd8fcca3fe7ad05d419d32998a06da',\n            'dev_requirement' => false,\n        ),\n        'guzzlehttp/psr7' => array(\n            'pretty_version' => '2.1.0',\n            'version' => '2.1.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../guzzlehttp/psr7',\n            'aliases' => array(),\n            'reference' => '089edd38f5b8abba6cb01567c2a8aaa47cec4c72',\n            'dev_requirement' => false,\n        ),\n        'jaeger/g-http' => array(\n            'pretty_version' => 'V1.7.2',\n            'version' => '1.7.2.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../jaeger/g-http',\n            'aliases' => array(),\n            'reference' => '82585ddd5e2c6651e37ab1d8166efcdbb6b293d4',\n            'dev_requirement' => false,\n        ),\n        'jaeger/phpquery-single' => array(\n            'pretty_version' => '1.0.1',\n            'version' => '1.0.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../jaeger/phpquery-single',\n            'aliases' => array(),\n            'reference' => 'fb80b4a0e5a337438d26e061ec3fb725c9f2a116',\n            'dev_requirement' => false,\n        ),\n        'jaeger/querylist' => array(\n            'pretty_version' => 'V4.2.8',\n            'version' => '4.2.8.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../jaeger/querylist',\n            'aliases' => array(),\n            'reference' => '39dc0ca9c668bec7a793e20472ccd7d26ef89ea4',\n            'dev_requirement' => false,\n        ),\n        'jaeger/querylist-puppeteer' => array(\n            'pretty_version' => '4.0.0',\n            'version' => '4.0.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../jaeger/querylist-puppeteer',\n            'aliases' => array(),\n            'reference' => 'c6bd5acc4c95022bea92ba1308841b863eab2cf0',\n            'dev_requirement' => false,\n        ),\n        'league/flysystem' => array(\n            'pretty_version' => '1.1.9',\n            'version' => '1.1.9.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../league/flysystem',\n            'aliases' => array(),\n            'reference' => '094defdb4a7001845300334e7c1ee2335925ef99',\n            'dev_requirement' => false,\n        ),\n        'league/mime-type-detection' => array(\n            'pretty_version' => '1.10.0',\n            'version' => '1.10.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../league/mime-type-detection',\n            'aliases' => array(),\n            'reference' => '3e4a35d756eedc67096f30240a68a3149120dae7',\n            'dev_requirement' => false,\n        ),\n        'nesk/puphpeteer' => array(\n            'pretty_version' => '1.6.0',\n            'version' => '1.6.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../nesk/puphpeteer',\n            'aliases' => array(),\n            'reference' => '21adf25d320f32b005cb3e2f9026616566015fcc',\n            'dev_requirement' => false,\n        ),\n        'nesk/rialto' => array(\n            'pretty_version' => '1.4.0',\n            'version' => '1.4.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../nesk/rialto',\n            'aliases' => array(),\n            'reference' => 'a3db615d845cca42135fa1e271b323ffe904b83c',\n            'dev_requirement' => false,\n        ),\n        'psr/cache' => array(\n            'pretty_version' => '2.0.0',\n            'version' => '2.0.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../psr/cache',\n            'aliases' => array(),\n            'reference' => '213f9dbc5b9bfbc4f8db86d2838dc968752ce13b',\n            'dev_requirement' => false,\n        ),\n        'psr/cache-implementation' => array(\n            'dev_requirement' => false,\n            'provided' => array(\n                0 => '^1.0',\n            ),\n        ),\n        'psr/http-client' => array(\n            'pretty_version' => '1.0.1',\n            'version' => '1.0.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../psr/http-client',\n            'aliases' => array(),\n            'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',\n            'dev_requirement' => false,\n        ),\n        'psr/http-client-implementation' => array(\n            'dev_requirement' => false,\n            'provided' => array(\n                0 => '1.0',\n            ),\n        ),\n        'psr/http-factory' => array(\n            'pretty_version' => '1.0.1',\n            'version' => '1.0.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../psr/http-factory',\n            'aliases' => array(),\n            'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',\n            'dev_requirement' => false,\n        ),\n        'psr/http-factory-implementation' => array(\n            'dev_requirement' => false,\n            'provided' => array(\n                0 => '1.0',\n            ),\n        ),\n        'psr/http-message' => array(\n            'pretty_version' => '1.0.1',\n            'version' => '1.0.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../psr/http-message',\n            'aliases' => array(),\n            'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',\n            'dev_requirement' => false,\n        ),\n        'psr/http-message-implementation' => array(\n            'dev_requirement' => false,\n            'provided' => array(\n                0 => '1.0',\n            ),\n        ),\n        'psr/log' => array(\n            'pretty_version' => '1.1.4',\n            'version' => '1.1.4.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../psr/log',\n            'aliases' => array(),\n            'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',\n            'dev_requirement' => false,\n        ),\n        'psr/simple-cache' => array(\n            'pretty_version' => '1.0.1',\n            'version' => '1.0.1.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../psr/simple-cache',\n            'aliases' => array(),\n            'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',\n            'dev_requirement' => false,\n        ),\n        'psr/simple-cache-implementation' => array(\n            'dev_requirement' => false,\n            'provided' => array(\n                0 => '^1.0',\n            ),\n        ),\n        'ralouphie/getallheaders' => array(\n            'pretty_version' => '3.0.3',\n            'version' => '3.0.3.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../ralouphie/getallheaders',\n            'aliases' => array(),\n            'reference' => '120b605dfeb996808c31b6477290a714d356e822',\n            'dev_requirement' => false,\n        ),\n        'symfony/deprecation-contracts' => array(\n            'pretty_version' => 'v3.0.0',\n            'version' => '3.0.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../symfony/deprecation-contracts',\n            'aliases' => array(),\n            'reference' => 'c726b64c1ccfe2896cb7df2e1331c357ad1c8ced',\n            'dev_requirement' => false,\n        ),\n        'symfony/polyfill-mbstring' => array(\n            'pretty_version' => 'v1.25.0',\n            'version' => '1.25.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',\n            'aliases' => array(),\n            'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',\n            'dev_requirement' => false,\n        ),\n        'symfony/polyfill-php80' => array(\n            'pretty_version' => 'v1.25.0',\n            'version' => '1.25.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../symfony/polyfill-php80',\n            'aliases' => array(),\n            'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c',\n            'dev_requirement' => false,\n        ),\n        'symfony/process' => array(\n            'pretty_version' => 'v5.4.7',\n            'version' => '5.4.7.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../symfony/process',\n            'aliases' => array(),\n            'reference' => '38a44b2517b470a436e1c944bf9b9ba3961137fb',\n            'dev_requirement' => false,\n        ),\n        'symfony/var-dumper' => array(\n            'pretty_version' => 'v5.4.6',\n            'version' => '5.4.6.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../symfony/var-dumper',\n            'aliases' => array(),\n            'reference' => '294e9da6e2e0dd404e983daa5aa74253d92c05d0',\n            'dev_requirement' => false,\n        ),\n        'tightenco/collect' => array(\n            'pretty_version' => '8.78.0',\n            'version' => '8.78.0.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../tightenco/collect',\n            'aliases' => array(),\n            'reference' => '3a42ca9b730a88e942fe05180d4f15e045464e40',\n            'dev_requirement' => false,\n        ),\n        'vierbergenlars/php-semver' => array(\n            'pretty_version' => '3.0.2',\n            'version' => '3.0.2.0',\n            'type' => 'library',\n            'install_path' => __DIR__ . '/../vierbergenlars/php-semver',\n            'aliases' => array(),\n            'reference' => 'be22b86be4c1133acc42fd1685276792024af5f9',\n            'dev_requirement' => false,\n        ),\n    ),\n);\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/CHANGELOG.md",
    "content": "# Change Log\n\nPlease refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version.\n\n## 7.4.1 - 2021-12-06\n\n### Changed\n\n- Replaced implicit URI to string coercion [#2946](https://github.com/guzzle/guzzle/pull/2946)\n- Allow `symfony/deprecation-contracts` version 3 [#2961](https://github.com/guzzle/guzzle/pull/2961)\n\n### Fixed\n\n- Only close curl handle if it's done [#2950](https://github.com/guzzle/guzzle/pull/2950)\n\n## 7.4.0 - 2021-10-18\n\n### Added\n\n- Support PHP 8.1 [#2929](https://github.com/guzzle/guzzle/pull/2929), [#2939](https://github.com/guzzle/guzzle/pull/2939)\n- Support `psr/log` version 2 and 3 [#2943](https://github.com/guzzle/guzzle/pull/2943)\n\n### Fixed\n\n- Make sure we always call `restore_error_handler()` [#2915](https://github.com/guzzle/guzzle/pull/2915)\n- Fix progress parameter type compatibility between the cURL and stream handlers [#2936](https://github.com/guzzle/guzzle/pull/2936)\n- Throw `InvalidArgumentException` when an incorrect `headers` array is provided [#2916](https://github.com/guzzle/guzzle/pull/2916), [#2942](https://github.com/guzzle/guzzle/pull/2942)\n\n### Changed\n\n- Be more strict with types [#2914](https://github.com/guzzle/guzzle/pull/2914), [#2917](https://github.com/guzzle/guzzle/pull/2917), [#2919](https://github.com/guzzle/guzzle/pull/2919), [#2945](https://github.com/guzzle/guzzle/pull/2945)\n\n## 7.3.0 - 2021-03-23\n\n### Added\n\n- Support for DER and P12 certificates [#2413](https://github.com/guzzle/guzzle/pull/2413)\n- Support the cURL (http://) scheme for StreamHandler proxies [#2850](https://github.com/guzzle/guzzle/pull/2850)\n- Support for `guzzlehttp/psr7:^2.0` [#2878](https://github.com/guzzle/guzzle/pull/2878)\n\n### Fixed\n\n- Handle exceptions on invalid header consistently between PHP versions and handlers [#2872](https://github.com/guzzle/guzzle/pull/2872)\n\n## 7.2.0 - 2020-10-10\n\n### Added\n\n- Support for PHP 8 [#2712](https://github.com/guzzle/guzzle/pull/2712), [#2715](https://github.com/guzzle/guzzle/pull/2715), [#2789](https://github.com/guzzle/guzzle/pull/2789)\n- Support passing a body summarizer to the http errors middleware [#2795](https://github.com/guzzle/guzzle/pull/2795)\n\n### Fixed\n\n- Handle exceptions during response creation [#2591](https://github.com/guzzle/guzzle/pull/2591)\n- Fix CURLOPT_ENCODING not to be overwritten [#2595](https://github.com/guzzle/guzzle/pull/2595)\n- Make sure the Request always has a body object [#2804](https://github.com/guzzle/guzzle/pull/2804)\n\n### Changed\n\n- The `TooManyRedirectsException` has a response [#2660](https://github.com/guzzle/guzzle/pull/2660)\n- Avoid \"functions\" from dependencies [#2712](https://github.com/guzzle/guzzle/pull/2712)\n\n### Deprecated\n\n- Using environment variable GUZZLE_CURL_SELECT_TIMEOUT [#2786](https://github.com/guzzle/guzzle/pull/2786)\n\n## 7.1.1 - 2020-09-30\n\n### Fixed\n\n- Incorrect EOF detection for response body streams on Windows.\n\n### Changed\n\n- We dont connect curl `sink` on HEAD requests.\n- Removed some PHP 5 workarounds\n\n## 7.1.0 - 2020-09-22\n\n### Added\n\n- `GuzzleHttp\\MessageFormatterInterface`\n\n### Fixed\n\n- Fixed issue that caused cookies with no value not to be stored.\n- On redirects, we allow all safe methods like GET, HEAD and OPTIONS.\n- Fixed logging on empty responses.\n- Make sure MessageFormatter::format returns string\n\n### Deprecated\n\n- All functions in `GuzzleHttp` has been deprecated. Use static methods on `Utils` instead.\n- `ClientInterface::getConfig()`\n- `Client::getConfig()`\n- `Client::__call()`\n- `Utils::defaultCaBundle()`\n- `CurlFactory::LOW_CURL_VERSION_NUMBER`\n\n## 7.0.1 - 2020-06-27\n\n* Fix multiply defined functions fatal error [#2699](https://github.com/guzzle/guzzle/pull/2699)\n\n## 7.0.0 - 2020-06-27\n\nNo changes since 7.0.0-rc1.\n\n## 7.0.0-rc1 - 2020-06-15\n\n### Changed\n\n* Use error level for logging errors in Middleware [#2629](https://github.com/guzzle/guzzle/pull/2629)\n* Disabled IDN support by default and require ext-intl to use it [#2675](https://github.com/guzzle/guzzle/pull/2675)\n\n## 7.0.0-beta2 - 2020-05-25\n\n### Added\n\n* Using `Utils` class instead of functions in the `GuzzleHttp` namespace. [#2546](https://github.com/guzzle/guzzle/pull/2546)\n* `ClientInterface::MAJOR_VERSION` [#2583](https://github.com/guzzle/guzzle/pull/2583)\n\n### Changed\n\n* Avoid the `getenv` function when unsafe [#2531](https://github.com/guzzle/guzzle/pull/2531)\n* Added real client methods [#2529](https://github.com/guzzle/guzzle/pull/2529)\n* Avoid functions due to global install conflicts [#2546](https://github.com/guzzle/guzzle/pull/2546)\n* Use Symfony intl-idn polyfill [#2550](https://github.com/guzzle/guzzle/pull/2550)\n* Adding methods for HTTP verbs like `Client::get()`, `Client::head()`, `Client::patch()` etc [#2529](https://github.com/guzzle/guzzle/pull/2529)\n* `ConnectException` extends `TransferException` [#2541](https://github.com/guzzle/guzzle/pull/2541)\n* Updated the default User Agent to \"GuzzleHttp/7\" [#2654](https://github.com/guzzle/guzzle/pull/2654)\n\n### Fixed\n\n* Various intl icu issues [#2626](https://github.com/guzzle/guzzle/pull/2626)\n\n### Removed\n\n* Pool option `pool_size` [#2528](https://github.com/guzzle/guzzle/pull/2528)\n\n## 7.0.0-beta1 - 2019-12-30\n\nThe diff might look very big but 95% of Guzzle users will be able to upgrade without modification.\nPlease see [the upgrade document](UPGRADING.md) that describes all BC breaking changes.\n\n### Added\n\n* Implement PSR-18 and dropped PHP 5 support [#2421](https://github.com/guzzle/guzzle/pull/2421) [#2474](https://github.com/guzzle/guzzle/pull/2474)\n* PHP 7 types [#2442](https://github.com/guzzle/guzzle/pull/2442) [#2449](https://github.com/guzzle/guzzle/pull/2449) [#2466](https://github.com/guzzle/guzzle/pull/2466) [#2497](https://github.com/guzzle/guzzle/pull/2497) [#2499](https://github.com/guzzle/guzzle/pull/2499)\n* IDN support for redirects [2424](https://github.com/guzzle/guzzle/pull/2424)\n\n### Changed\n\n* Dont allow passing null as third argument to `BadResponseException::__construct()` [#2427](https://github.com/guzzle/guzzle/pull/2427)\n* Use SAPI constant instead of method call [#2450](https://github.com/guzzle/guzzle/pull/2450)\n* Use native function invocation [#2444](https://github.com/guzzle/guzzle/pull/2444)\n* Better defaults for PHP installations with old ICU lib [2454](https://github.com/guzzle/guzzle/pull/2454)\n* Added visibility to all constants [#2462](https://github.com/guzzle/guzzle/pull/2462)\n* Dont allow passing `null` as URI to `Client::request()` and `Client::requestAsync()` [#2461](https://github.com/guzzle/guzzle/pull/2461)\n* Widen the exception argument to throwable [#2495](https://github.com/guzzle/guzzle/pull/2495)\n\n### Fixed\n\n* Logging when Promise rejected with a string [#2311](https://github.com/guzzle/guzzle/pull/2311)\n\n### Removed\n\n* Class `SeekException` [#2162](https://github.com/guzzle/guzzle/pull/2162)\n* `RequestException::getResponseBodySummary()` [#2425](https://github.com/guzzle/guzzle/pull/2425)\n* `CookieJar::getCookieValue()` [#2433](https://github.com/guzzle/guzzle/pull/2433)\n* `uri_template()` and `UriTemplate` [#2440](https://github.com/guzzle/guzzle/pull/2440)\n* Request options `save_to` and `exceptions` [#2464](https://github.com/guzzle/guzzle/pull/2464)\n\n## 6.5.2 - 2019-12-23\n\n* idn_to_ascii() fix for old PHP versions [#2489](https://github.com/guzzle/guzzle/pull/2489)\n\n## 6.5.1 - 2019-12-21\n\n* Better defaults for PHP installations with old ICU lib [#2454](https://github.com/guzzle/guzzle/pull/2454)\n* IDN support for redirects [#2424](https://github.com/guzzle/guzzle/pull/2424)\n\n## 6.5.0 - 2019-12-07\n\n* Improvement: Added support for reset internal queue in MockHandler. [#2143](https://github.com/guzzle/guzzle/pull/2143)\n* Improvement: Added support to pass arbitrary options to `curl_multi_init`. [#2287](https://github.com/guzzle/guzzle/pull/2287)\n* Fix: Gracefully handle passing `null` to the `header` option. [#2132](https://github.com/guzzle/guzzle/pull/2132)\n* Fix: `RetryMiddleware` did not do exponential delay between retires due unit mismatch. [#2132](https://github.com/guzzle/guzzle/pull/2132)\n* Fix: Prevent undefined offset when using array for ssl_key options. [#2348](https://github.com/guzzle/guzzle/pull/2348)\n* Deprecated `ClientInterface::VERSION`\n\n## 6.4.1 - 2019-10-23\n\n* No `guzzle.phar` was created in 6.4.0 due expired API token. This release will fix that\n* Added `parent::__construct()` to `FileCookieJar` and `SessionCookieJar`\n\n## 6.4.0 - 2019-10-23\n\n* Improvement: Improved error messages when using curl < 7.21.2 [#2108](https://github.com/guzzle/guzzle/pull/2108)\n* Fix: Test if response is readable before returning a summary in `RequestException::getResponseBodySummary()` [#2081](https://github.com/guzzle/guzzle/pull/2081)\n* Fix: Add support for GUZZLE_CURL_SELECT_TIMEOUT environment variable [#2161](https://github.com/guzzle/guzzle/pull/2161)\n* Improvement: Added `GuzzleHttp\\Exception\\InvalidArgumentException` [#2163](https://github.com/guzzle/guzzle/pull/2163)\n* Improvement: Added `GuzzleHttp\\_current_time()` to use `hrtime()` if that function exists. [#2242](https://github.com/guzzle/guzzle/pull/2242)\n* Improvement: Added curl's `appconnect_time` in `TransferStats` [#2284](https://github.com/guzzle/guzzle/pull/2284)\n* Improvement: Make GuzzleException extend Throwable wherever it's available [#2273](https://github.com/guzzle/guzzle/pull/2273)\n* Fix: Prevent concurrent writes to file when saving `CookieJar` [#2335](https://github.com/guzzle/guzzle/pull/2335)\n* Improvement: Update `MockHandler` so we can test transfer time [#2362](https://github.com/guzzle/guzzle/pull/2362)\n\n## 6.3.3 - 2018-04-22\n\n* Fix: Default headers when decode_content is specified\n\n\n## 6.3.2 - 2018-03-26\n\n* Fix: Release process\n\n\n## 6.3.1 - 2018-03-26\n\n* Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014)\n* Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012)\n* Bug fix: Malformed domain that contains a \"/\" [#1999](https://github.com/guzzle/guzzle/pull/1999)\n* Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998)\n* Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953)\n* Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915)\n* Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916)\n\n+ Minor code cleanups, documentation fixes and clarifications.\n\n\n## 6.3.0 - 2017-06-22\n\n* Feature: force IP resolution (ipv4 or ipv6) [#1608](https://github.com/guzzle/guzzle/pull/1608), [#1659](https://github.com/guzzle/guzzle/pull/1659)\n* Improvement: Don't include summary in exception message when body is empty [#1621](https://github.com/guzzle/guzzle/pull/1621)\n* Improvement: Handle `on_headers` option in MockHandler [#1580](https://github.com/guzzle/guzzle/pull/1580)\n* Improvement: Added SUSE Linux CA path [#1609](https://github.com/guzzle/guzzle/issues/1609)\n* Improvement: Use class reference for getting the name of the class instead of using hardcoded strings [#1641](https://github.com/guzzle/guzzle/pull/1641)\n* Feature: Added `read_timeout` option [#1611](https://github.com/guzzle/guzzle/pull/1611)\n* Bug fix: PHP 7.x fixes [#1685](https://github.com/guzzle/guzzle/pull/1685), [#1686](https://github.com/guzzle/guzzle/pull/1686), [#1811](https://github.com/guzzle/guzzle/pull/1811)\n* Deprecation: BadResponseException instantiation without a response [#1642](https://github.com/guzzle/guzzle/pull/1642)\n* Feature: Added NTLM auth [#1569](https://github.com/guzzle/guzzle/pull/1569)\n* Feature: Track redirect HTTP status codes [#1711](https://github.com/guzzle/guzzle/pull/1711)\n* Improvement: Check handler type during construction [#1745](https://github.com/guzzle/guzzle/pull/1745)\n* Improvement: Always include the Content-Length if there's a body [#1721](https://github.com/guzzle/guzzle/pull/1721)\n* Feature: Added convenience method to access a cookie by name [#1318](https://github.com/guzzle/guzzle/pull/1318)\n* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684)\n* Improvement:  \tUse `\\GuzzleHttp\\Promise\\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827)\n\n\n+ Minor code cleanups, documentation fixes and clarifications.\n\n## 6.2.3 - 2017-02-28\n\n* Fix deprecations with guzzle/psr7 version 1.4\n\n## 6.2.2 - 2016-10-08\n\n* Allow to pass nullable Response to delay callable\n* Only add scheme when host is present\n* Fix drain case where content-length is the literal string zero\n* Obfuscate in-URL credentials in exceptions\n\n## 6.2.1 - 2016-07-18\n\n* Address HTTP_PROXY security vulnerability, CVE-2016-5385:\n  https://httpoxy.org/\n* Fixing timeout bug with StreamHandler:\n  https://github.com/guzzle/guzzle/pull/1488\n* Only read up to `Content-Length` in PHP StreamHandler to avoid timeouts when\n  a server does not honor `Connection: close`.\n* Ignore URI fragment when sending requests.\n\n## 6.2.0 - 2016-03-21\n\n* Feature: added `GuzzleHttp\\json_encode` and `GuzzleHttp\\json_decode`.\n  https://github.com/guzzle/guzzle/pull/1389\n* Bug fix: Fix sleep calculation when waiting for delayed requests.\n  https://github.com/guzzle/guzzle/pull/1324\n* Feature: More flexible history containers.\n  https://github.com/guzzle/guzzle/pull/1373\n* Bug fix: defer sink stream opening in StreamHandler.\n  https://github.com/guzzle/guzzle/pull/1377\n* Bug fix: do not attempt to escape cookie values.\n  https://github.com/guzzle/guzzle/pull/1406\n* Feature: report original content encoding and length on decoded responses.\n  https://github.com/guzzle/guzzle/pull/1409\n* Bug fix: rewind seekable request bodies before dispatching to cURL.\n  https://github.com/guzzle/guzzle/pull/1422\n* Bug fix: provide an empty string to `http_build_query` for HHVM workaround.\n  https://github.com/guzzle/guzzle/pull/1367\n\n## 6.1.1 - 2015-11-22\n\n* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler\n  https://github.com/guzzle/guzzle/commit/911bcbc8b434adce64e223a6d1d14e9a8f63e4e4\n* Feature: HandlerStack is now more generic.\n  https://github.com/guzzle/guzzle/commit/f2102941331cda544745eedd97fc8fd46e1ee33e\n* Bug fix: setting verify to false in the StreamHandler now disables peer\n  verification. https://github.com/guzzle/guzzle/issues/1256\n* Feature: Middleware now uses an exception factory, including more error\n  context. https://github.com/guzzle/guzzle/pull/1282\n* Feature: better support for disabled functions.\n  https://github.com/guzzle/guzzle/pull/1287\n* Bug fix: fixed regression where MockHandler was not using `sink`.\n  https://github.com/guzzle/guzzle/pull/1292\n\n## 6.1.0 - 2015-09-08\n\n* Feature: Added the `on_stats` request option to provide access to transfer\n  statistics for requests. https://github.com/guzzle/guzzle/pull/1202\n* Feature: Added the ability to persist session cookies in CookieJars.\n  https://github.com/guzzle/guzzle/pull/1195\n* Feature: Some compatibility updates for Google APP Engine\n  https://github.com/guzzle/guzzle/pull/1216\n* Feature: Added support for NO_PROXY to prevent the use of a proxy based on\n  a simple set of rules. https://github.com/guzzle/guzzle/pull/1197\n* Feature: Cookies can now contain square brackets.\n  https://github.com/guzzle/guzzle/pull/1237\n* Bug fix: Now correctly parsing `=` inside of quotes in Cookies.\n  https://github.com/guzzle/guzzle/pull/1232\n* Bug fix: Cusotm cURL options now correctly override curl options of the\n  same name. https://github.com/guzzle/guzzle/pull/1221\n* Bug fix: Content-Type header is now added when using an explicitly provided\n  multipart body. https://github.com/guzzle/guzzle/pull/1218\n* Bug fix: Now ignoring Set-Cookie headers that have no name.\n* Bug fix: Reason phrase is no longer cast to an int in some cases in the\n  cURL handler. https://github.com/guzzle/guzzle/pull/1187\n* Bug fix: Remove the Authorization header when redirecting if the Host\n  header changes. https://github.com/guzzle/guzzle/pull/1207\n* Bug fix: Cookie path matching fixes\n  https://github.com/guzzle/guzzle/issues/1129\n* Bug fix: Fixing the cURL `body_as_string` setting\n  https://github.com/guzzle/guzzle/pull/1201\n* Bug fix: quotes are no longer stripped when parsing cookies.\n  https://github.com/guzzle/guzzle/issues/1172\n* Bug fix: `form_params` and `query` now always uses the `&` separator.\n  https://github.com/guzzle/guzzle/pull/1163\n* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set.\n  https://github.com/guzzle/guzzle/pull/1189\n\n## 6.0.2 - 2015-07-04\n\n* Fixed a memory leak in the curl handlers in which references to callbacks\n  were not being removed by `curl_reset`.\n* Cookies are now extracted properly before redirects.\n* Cookies now allow more character ranges.\n* Decoded Content-Encoding responses are now modified to correctly reflect\n  their state if the encoding was automatically removed by a handler. This\n  means that the `Content-Encoding` header may be removed an the\n  `Content-Length` modified to reflect the message size after removing the\n  encoding.\n* Added a more explicit error message when trying to use `form_params` and\n  `multipart` in the same request.\n* Several fixes for HHVM support.\n* Functions are now conditionally required using an additional level of\n  indirection to help with global Composer installations.\n\n## 6.0.1 - 2015-05-27\n\n* Fixed a bug with serializing the `query` request option where the `&`\n  separator was missing.\n* Added a better error message for when `body` is provided as an array. Please\n  use `form_params` or `multipart` instead.\n* Various doc fixes.\n\n## 6.0.0 - 2015-05-26\n\n* See the UPGRADING.md document for more information.\n* Added `multipart` and `form_params` request options.\n* Added `synchronous` request option.\n* Added the `on_headers` request option.\n* Fixed `expect` handling.\n* No longer adding default middlewares in the client ctor. These need to be\n  present on the provided handler in order to work.\n* Requests are no longer initiated when sending async requests with the\n  CurlMultiHandler. This prevents unexpected recursion from requests completing\n  while ticking the cURL loop.\n* Removed the semantics of setting `default` to `true`. This is no longer\n  required now that the cURL loop is not ticked for async requests.\n* Added request and response logging middleware.\n* No longer allowing self signed certificates when using the StreamHandler.\n* Ensuring that `sink` is valid if saving to a file.\n* Request exceptions now include a \"handler context\" which provides handler\n  specific contextual information.\n* Added `GuzzleHttp\\RequestOptions` to allow request options to be applied\n  using constants.\n* `$maxHandles` has been removed from CurlMultiHandler.\n* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.\n\n## 5.3.0 - 2015-05-19\n\n* Mock now supports `save_to`\n* Marked `AbstractRequestEvent::getTransaction()` as public.\n* Fixed a bug in which multiple headers using different casing would overwrite\n  previous headers in the associative array.\n* Added `Utils::getDefaultHandler()`\n* Marked `GuzzleHttp\\Client::getDefaultUserAgent` as deprecated.\n* URL scheme is now always lowercased.\n\n## 6.0.0-beta.1\n\n* Requires PHP >= 5.5\n* Updated to use PSR-7\n  * Requires immutable messages, which basically means an event based system\n    owned by a request instance is no longer possible.\n  * Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7).\n  * Removed the dependency on `guzzlehttp/streams`. These stream abstractions\n    are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\\Psr7`\n    namespace.\n* Added middleware and handler system\n  * Replaced the Guzzle event and subscriber system with a middleware system.\n  * No longer depends on RingPHP, but rather places the HTTP handlers directly\n    in Guzzle, operating on PSR-7 messages.\n  * Retry logic is now encapsulated in `GuzzleHttp\\Middleware::retry`, which\n    means the `guzzlehttp/retry-subscriber` is now obsolete.\n  * Mocking responses is now handled using `GuzzleHttp\\Handler\\MockHandler`.\n* Asynchronous responses\n  * No longer supports the `future` request option to send an async request.\n    Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`,\n    `getAsync`, etc.).\n  * Utilizing `GuzzleHttp\\Promise` instead of React's promise library to avoid\n    recursion required by chaining and forwarding react promises. See\n    https://github.com/guzzle/promises\n  * Added `requestAsync` and `sendAsync` to send request asynchronously.\n  * Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests\n    asynchronously.\n* Request options\n  * POST and form updates\n    * Added the `form_fields` and `form_files` request options.\n    * Removed the `GuzzleHttp\\Post` namespace.\n    * The `body` request option no longer accepts an array for POST requests.\n  * The `exceptions` request option has been deprecated in favor of the\n    `http_errors` request options.\n  * The `save_to` request option has been deprecated in favor of `sink` request\n    option.\n* Clients no longer accept an array of URI template string and variables for\n  URI variables. You will need to expand URI templates before passing them\n  into a client constructor or request method.\n* Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are\n  now magic methods that will send synchronous requests.\n* Replaced `Utils.php` with plain functions in `functions.php`.\n* Removed `GuzzleHttp\\Collection`.\n* Removed `GuzzleHttp\\BatchResults`. Batched pool results are now returned as\n  an array.\n* Removed `GuzzleHttp\\Query`. Query string handling is now handled using an\n  associative array passed into the `query` request option. The query string\n  is serialized using PHP's `http_build_query`. If you need more control, you\n  can pass the query string in as a string.\n* `GuzzleHttp\\QueryParser` has been replaced with the\n  `GuzzleHttp\\Psr7\\parse_query`.\n\n## 5.2.0 - 2015-01-27\n\n* Added `AppliesHeadersInterface` to make applying headers to a request based\n  on the body more generic and not specific to `PostBodyInterface`.\n* Reduced the number of stack frames needed to send requests.\n* Nested futures are now resolved in the client rather than the RequestFsm\n* Finishing state transitions is now handled in the RequestFsm rather than the\n  RingBridge.\n* Added a guard in the Pool class to not use recursion for request retries.\n\n## 5.1.0 - 2014-12-19\n\n* Pool class no longer uses recursion when a request is intercepted.\n* The size of a Pool can now be dynamically adjusted using a callback.\n  See https://github.com/guzzle/guzzle/pull/943.\n* Setting a request option to `null` when creating a request with a client will\n  ensure that the option is not set. This allows you to overwrite default\n  request options on a per-request basis.\n  See https://github.com/guzzle/guzzle/pull/937.\n* Added the ability to limit which protocols are allowed for redirects by\n  specifying a `protocols` array in the `allow_redirects` request option.\n* Nested futures due to retries are now resolved when waiting for synchronous\n  responses. See https://github.com/guzzle/guzzle/pull/947.\n* `\"0\"` is now an allowed URI path. See\n  https://github.com/guzzle/guzzle/pull/935.\n* `Query` no longer typehints on the `$query` argument in the constructor,\n  allowing for strings and arrays.\n* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle\n  specific exceptions if necessary.\n\n## 5.0.3 - 2014-11-03\n\nThis change updates query strings so that they are treated as un-encoded values\nby default where the value represents an un-encoded value to send over the\nwire. A Query object then encodes the value before sending over the wire. This\nmeans that even value query string values (e.g., \":\") are url encoded. This\nmakes the Query class match PHP's http_build_query function. However, if you\nwant to send requests over the wire using valid query string characters that do\nnot need to be encoded, then you can provide a string to Url::setQuery() and\npass true as the second argument to specify that the query string is a raw\nstring that should not be parsed or encoded (unless a call to getQuery() is\nsubsequently made, forcing the query-string to be converted into a Query\nobject).\n\n## 5.0.2 - 2014-10-30\n\n* Added a trailing `\\r\\n` to multipart/form-data payloads. See\n  https://github.com/guzzle/guzzle/pull/871\n* Added a `GuzzleHttp\\Pool::send()` convenience method to match the docs.\n* Status codes are now returned as integers. See\n  https://github.com/guzzle/guzzle/issues/881\n* No longer overwriting an existing `application/x-www-form-urlencoded` header\n  when sending POST requests, allowing for customized headers. See\n  https://github.com/guzzle/guzzle/issues/877\n* Improved path URL serialization.\n\n  * No longer double percent-encoding characters in the path or query string if\n    they are already encoded.\n  * Now properly encoding the supplied path to a URL object, instead of only\n    encoding ' ' and '?'.\n  * Note: This has been changed in 5.0.3 to now encode query string values by\n    default unless the `rawString` argument is provided when setting the query\n    string on a URL: Now allowing many more characters to be present in the\n    query string without being percent encoded. See https://tools.ietf.org/html/rfc3986#appendix-A\n\n## 5.0.1 - 2014-10-16\n\nBugfix release.\n\n* Fixed an issue where connection errors still returned response object in\n  error and end events event though the response is unusable. This has been\n  corrected so that a response is not returned in the `getResponse` method of\n  these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867\n* Fixed an issue where transfer statistics were not being populated in the\n  RingBridge. https://github.com/guzzle/guzzle/issues/866\n\n## 5.0.0 - 2014-10-12\n\nAdding support for non-blocking responses and some minor API cleanup.\n\n### New Features\n\n* Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.\n* Added a public API for creating a default HTTP adapter.\n* Updated the redirect plugin to be non-blocking so that redirects are sent\n  concurrently. Other plugins like this can now be updated to be non-blocking.\n* Added a \"progress\" event so that you can get upload and download progress\n  events.\n* Added `GuzzleHttp\\Pool` which implements FutureInterface and transfers\n  requests concurrently using a capped pool size as efficiently as possible.\n* Added `hasListeners()` to EmitterInterface.\n* Removed `GuzzleHttp\\ClientInterface::sendAll` and marked\n  `GuzzleHttp\\Client::sendAll` as deprecated (it's still there, just not the\n  recommended way).\n\n### Breaking changes\n\nThe breaking changes in this release are relatively minor. The biggest thing to\nlook out for is that request and response objects no longer implement fluent\ninterfaces.\n\n* Removed the fluent interfaces (i.e., `return $this`) from requests,\n  responses, `GuzzleHttp\\Collection`, `GuzzleHttp\\Url`,\n  `GuzzleHttp\\Query`, `GuzzleHttp\\Post\\PostBody`, and\n  `GuzzleHttp\\Cookie\\SetCookie`. This blog post provides a good outline of\n  why I did this: https://ocramius.github.io/blog/fluent-interfaces-are-evil/.\n  This also makes the Guzzle message interfaces compatible with the current\n  PSR-7 message proposal.\n* Removed \"functions.php\", so that Guzzle is truly PSR-4 compliant. Except\n  for the HTTP request functions from function.php, these functions are now\n  implemented in `GuzzleHttp\\Utils` using camelCase. `GuzzleHttp\\json_decode`\n  moved to `GuzzleHttp\\Utils::jsonDecode`. `GuzzleHttp\\get_path` moved to\n  `GuzzleHttp\\Utils::getPath`. `GuzzleHttp\\set_path` moved to\n  `GuzzleHttp\\Utils::setPath`. `GuzzleHttp\\batch` should now be\n  `GuzzleHttp\\Pool::batch`, which returns an `objectStorage`. Using functions.php\n  caused problems for many users: they aren't PSR-4 compliant, require an\n  explicit include, and needed an if-guard to ensure that the functions are not\n  declared multiple times.\n* Rewrote adapter layer.\n    * Removing all classes from `GuzzleHttp\\Adapter`, these are now\n      implemented as callables that are stored in `GuzzleHttp\\Ring\\Client`.\n    * Removed the concept of \"parallel adapters\". Sending requests serially or\n      concurrently is now handled using a single adapter.\n    * Moved `GuzzleHttp\\Adapter\\Transaction` to `GuzzleHttp\\Transaction`. The\n      Transaction object now exposes the request, response, and client as public\n      properties. The getters and setters have been removed.\n* Removed the \"headers\" event. This event was only useful for changing the\n  body a response once the headers of the response were known. You can implement\n  a similar behavior in a number of ways. One example might be to use a\n  FnStream that has access to the transaction being sent. For example, when the\n  first byte is written, you could check if the response headers match your\n  expectations, and if so, change the actual stream body that is being\n  written to.\n* Removed the `asArray` parameter from\n  `GuzzleHttp\\Message\\MessageInterface::getHeader`. If you want to get a header\n  value as an array, then use the newly added `getHeaderAsArray()` method of\n  `MessageInterface`. This change makes the Guzzle interfaces compatible with\n  the PSR-7 interfaces.\n* `GuzzleHttp\\Message\\MessageFactory` no longer allows subclasses to add\n  custom request options using double-dispatch (this was an implementation\n  detail). Instead, you should now provide an associative array to the\n  constructor which is a mapping of the request option name mapping to a\n  function that applies the option value to a request.\n* Removed the concept of \"throwImmediately\" from exceptions and error events.\n  This control mechanism was used to stop a transfer of concurrent requests\n  from completing. This can now be handled by throwing the exception or by\n  cancelling a pool of requests or each outstanding future request individually.\n* Updated to \"GuzzleHttp\\Streams\" 3.0.\n    * `GuzzleHttp\\Stream\\StreamInterface::getContents()` no longer accepts a\n      `maxLen` parameter. This update makes the Guzzle streams project\n      compatible with the current PSR-7 proposal.\n    * `GuzzleHttp\\Stream\\Stream::__construct`,\n      `GuzzleHttp\\Stream\\Stream::factory`, and\n      `GuzzleHttp\\Stream\\Utils::create` no longer accept a size in the second\n      argument. They now accept an associative array of options, including the\n      \"size\" key and \"metadata\" key which can be used to provide custom metadata.\n\n## 4.2.2 - 2014-09-08\n\n* Fixed a memory leak in the CurlAdapter when reusing cURL handles.\n* No longer using `request_fulluri` in stream adapter proxies.\n* Relative redirects are now based on the last response, not the first response.\n\n## 4.2.1 - 2014-08-19\n\n* Ensuring that the StreamAdapter does not always add a Content-Type header\n* Adding automated github releases with a phar and zip\n\n## 4.2.0 - 2014-08-17\n\n* Now merging in default options using a case-insensitive comparison.\n  Closes https://github.com/guzzle/guzzle/issues/767\n* Added the ability to automatically decode `Content-Encoding` response bodies\n  using the `decode_content` request option. This is set to `true` by default\n  to decode the response body if it comes over the wire with a\n  `Content-Encoding`. Set this value to `false` to disable decoding the\n  response content, and pass a string to provide a request `Accept-Encoding`\n  header and turn on automatic response decoding. This feature now allows you\n  to pass an `Accept-Encoding` header in the headers of a request but still\n  disable automatic response decoding.\n  Closes https://github.com/guzzle/guzzle/issues/764\n* Added the ability to throw an exception immediately when transferring\n  requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760\n* Updating guzzlehttp/streams dependency to ~2.1\n* No longer utilizing the now deprecated namespaced methods from the stream\n  package.\n\n## 4.1.8 - 2014-08-14\n\n* Fixed an issue in the CurlFactory that caused setting the `stream=false`\n  request option to throw an exception.\n  See: https://github.com/guzzle/guzzle/issues/769\n* TransactionIterator now calls rewind on the inner iterator.\n  See: https://github.com/guzzle/guzzle/pull/765\n* You can now set the `Content-Type` header to `multipart/form-data`\n  when creating POST requests to force multipart bodies.\n  See https://github.com/guzzle/guzzle/issues/768\n\n## 4.1.7 - 2014-08-07\n\n* Fixed an error in the HistoryPlugin that caused the same request and response\n  to be logged multiple times when an HTTP protocol error occurs.\n* Ensuring that cURL does not add a default Content-Type when no Content-Type\n  has been supplied by the user. This prevents the adapter layer from modifying\n  the request that is sent over the wire after any listeners may have already\n  put the request in a desired state (e.g., signed the request).\n* Throwing an exception when you attempt to send requests that have the\n  \"stream\" set to true in parallel using the MultiAdapter.\n* Only calling curl_multi_select when there are active cURL handles. This was\n  previously changed and caused performance problems on some systems due to PHP\n  always selecting until the maximum select timeout.\n* Fixed a bug where multipart/form-data POST fields were not correctly\n  aggregated (e.g., values with \"&\").\n\n## 4.1.6 - 2014-08-03\n\n* Added helper methods to make it easier to represent messages as strings,\n  including getting the start line and getting headers as a string.\n\n## 4.1.5 - 2014-08-02\n\n* Automatically retrying cURL \"Connection died, retrying a fresh connect\"\n  errors when possible.\n* cURL implementation cleanup\n* Allowing multiple event subscriber listeners to be registered per event by\n  passing an array of arrays of listener configuration.\n\n## 4.1.4 - 2014-07-22\n\n* Fixed a bug that caused multi-part POST requests with more than one field to\n  serialize incorrectly.\n* Paths can now be set to \"0\"\n* `ResponseInterface::xml` now accepts a `libxml_options` option and added a\n  missing default argument that was required when parsing XML response bodies.\n* A `save_to` stream is now created lazily, which means that files are not\n  created on disk unless a request succeeds.\n\n## 4.1.3 - 2014-07-15\n\n* Various fixes to multipart/form-data POST uploads\n* Wrapping function.php in an if-statement to ensure Guzzle can be used\n  globally and in a Composer install\n* Fixed an issue with generating and merging in events to an event array\n* POST headers are only applied before sending a request to allow you to change\n  the query aggregator used before uploading\n* Added much more robust query string parsing\n* Fixed various parsing and normalization issues with URLs\n* Fixing an issue where multi-valued headers were not being utilized correctly\n  in the StreamAdapter\n\n## 4.1.2 - 2014-06-18\n\n* Added support for sending payloads with GET requests\n\n## 4.1.1 - 2014-06-08\n\n* Fixed an issue related to using custom message factory options in subclasses\n* Fixed an issue with nested form fields in a multi-part POST\n* Fixed an issue with using the `json` request option for POST requests\n* Added `ToArrayInterface` to `GuzzleHttp\\Cookie\\CookieJar`\n\n## 4.1.0 - 2014-05-27\n\n* Added a `json` request option to easily serialize JSON payloads.\n* Added a `GuzzleHttp\\json_decode()` wrapper to safely parse JSON.\n* Added `setPort()` and `getPort()` to `GuzzleHttp\\Message\\RequestInterface`.\n* Added the ability to provide an emitter to a client in the client constructor.\n* Added the ability to persist a cookie session using $_SESSION.\n* Added a trait that can be used to add event listeners to an iterator.\n* Removed request method constants from RequestInterface.\n* Fixed warning when invalid request start-lines are received.\n* Updated MessageFactory to work with custom request option methods.\n* Updated cacert bundle to latest build.\n\n4.0.2 (2014-04-16)\n------------------\n\n* Proxy requests using the StreamAdapter now properly use request_fulluri (#632)\n* Added the ability to set scalars as POST fields (#628)\n\n## 4.0.1 - 2014-04-04\n\n* The HTTP status code of a response is now set as the exception code of\n  RequestException objects.\n* 303 redirects will now correctly switch from POST to GET requests.\n* The default parallel adapter of a client now correctly uses the MultiAdapter.\n* HasDataTrait now initializes the internal data array as an empty array so\n  that the toArray() method always returns an array.\n\n## 4.0.0 - 2014-03-29\n\n* For information on changes and upgrading, see:\n  https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40\n* Added `GuzzleHttp\\batch()` as a convenience function for sending requests in\n  parallel without needing to write asynchronous code.\n* Restructured how events are added to `GuzzleHttp\\ClientInterface::sendAll()`.\n  You can now pass a callable or an array of associative arrays where each\n  associative array contains the \"fn\", \"priority\", and \"once\" keys.\n\n## 4.0.0.rc-2 - 2014-03-25\n\n* Removed `getConfig()` and `setConfig()` from clients to avoid confusion\n  around whether things like base_url, message_factory, etc. should be able to\n  be retrieved or modified.\n* Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface\n* functions.php functions were renamed using snake_case to match PHP idioms\n* Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and\n  `GUZZLE_CURL_SELECT_TIMEOUT` environment variables\n* Added the ability to specify custom `sendAll()` event priorities\n* Added the ability to specify custom stream context options to the stream\n  adapter.\n* Added a functions.php function for `get_path()` and `set_path()`\n* CurlAdapter and MultiAdapter now use a callable to generate curl resources\n* MockAdapter now properly reads a body and emits a `headers` event\n* Updated Url class to check if a scheme and host are set before adding \":\"\n  and \"//\". This allows empty Url (e.g., \"\") to be serialized as \"\".\n* Parsing invalid XML no longer emits warnings\n* Curl classes now properly throw AdapterExceptions\n* Various performance optimizations\n* Streams are created with the faster `Stream\\create()` function\n* Marked deprecation_proxy() as internal\n* Test server is now a collection of static methods on a class\n\n## 4.0.0-rc.1 - 2014-03-15\n\n* See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40\n\n## 3.8.1 - 2014-01-28\n\n* Bug: Always using GET requests when redirecting from a 303 response\n* Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in\n  `Guzzle\\Http\\ClientInterface::setSslVerification()`\n* Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL\n* Bug: The body of a request can now be set to `\"0\"`\n* Sending PHP stream requests no longer forces `HTTP/1.0`\n* Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of\n  each sub-exception\n* Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than\n  clobbering everything).\n* Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)\n* Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.\n  For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.\n* Now properly escaping the regular expression delimiter when matching Cookie domains.\n* Network access is now disabled when loading XML documents\n\n## 3.8.0 - 2013-12-05\n\n* Added the ability to define a POST name for a file\n* JSON response parsing now properly walks additionalProperties\n* cURL error code 18 is now retried automatically in the BackoffPlugin\n* Fixed a cURL error when URLs contain fragments\n* Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were\n  CurlExceptions\n* CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)\n* Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`\n* Fixed a bug that was encountered when parsing empty header parameters\n* UriTemplate now has a `setRegex()` method to match the docs\n* The `debug` request parameter now checks if it is truthy rather than if it exists\n* Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin\n* Added the ability to combine URLs using strict RFC 3986 compliance\n* Command objects can now return the validation errors encountered by the command\n* Various fixes to cache revalidation (#437 and 29797e5)\n* Various fixes to the AsyncPlugin\n* Cleaned up build scripts\n\n## 3.7.4 - 2013-10-02\n\n* Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)\n* Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp\n  (see https://github.com/aws/aws-sdk-php/issues/147)\n* Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots\n* Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)\n* Updated the bundled cacert.pem (#419)\n* OauthPlugin now supports adding authentication to headers or query string (#425)\n\n## 3.7.3 - 2013-09-08\n\n* Added the ability to get the exception associated with a request/command when using `MultiTransferException` and\n  `CommandTransferException`.\n* Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description\n* Schemas are only injected into response models when explicitly configured.\n* No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of\n  an EntityBody.\n* Bug fix: ChunkedIterator can now properly chunk a \\Traversable as well as an \\Iterator.\n* Bug fix: FilterIterator now relies on `\\Iterator` instead of `\\Traversable`.\n* Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()\n* Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin\n* Bug fix: Visiting XML attributes first before visiting XML children when serializing requests\n* Bug fix: Properly parsing headers that contain commas contained in quotes\n* Bug fix: mimetype guessing based on a filename is now case-insensitive\n\n## 3.7.2 - 2013-08-02\n\n* Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander\n  See https://github.com/guzzle/guzzle/issues/371\n* Bug fix: Cookie domains are now matched correctly according to RFC 6265\n  See https://github.com/guzzle/guzzle/issues/377\n* Bug fix: GET parameters are now used when calculating an OAuth signature\n* Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted\n* `Guzzle\\Common\\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched\n* `Guzzle\\Http\\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.\n  See https://github.com/guzzle/guzzle/issues/379\n* Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See\n  https://github.com/guzzle/guzzle/pull/380\n* cURL multi cleanup and optimizations\n\n## 3.7.1 - 2013-07-05\n\n* Bug fix: Setting default options on a client now works\n* Bug fix: Setting options on HEAD requests now works. See #352\n* Bug fix: Moving stream factory before send event to before building the stream. See #353\n* Bug fix: Cookies no longer match on IP addresses per RFC 6265\n* Bug fix: Correctly parsing header parameters that are in `<>` and quotes\n* Added `cert` and `ssl_key` as request options\n* `Host` header can now diverge from the host part of a URL if the header is set manually\n* `Guzzle\\Service\\Command\\LocationVisitor\\Request\\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter\n* OAuth parameters are only added via the plugin if they aren't already set\n* Exceptions are now thrown when a URL cannot be parsed\n* Returning `false` if `Guzzle\\Http\\EntityBody::getContentMd5()` fails\n* Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin\n\n## 3.7.0 - 2013-06-10\n\n* See UPGRADING.md for more information on how to upgrade.\n* Requests now support the ability to specify an array of $options when creating a request to more easily modify a\n  request. You can pass a 'request.options' configuration setting to a client to apply default request options to\n  every request created by a client (e.g. default query string variables, headers, curl options, etc.).\n* Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\\Guzzle`.\n  See `Guzzle\\Http\\StaticClient::mount`.\n* Added `command.request_options` to `Guzzle\\Service\\Command\\AbstractCommand` to pass request options to requests\n      created by a command (e.g. custom headers, query string variables, timeout settings, etc.).\n* Stream size in `Guzzle\\Stream\\PhpStreamRequestFactory` will now be set if Content-Length is returned in the\n  headers of a response\n* Added `Guzzle\\Common\\Collection::setPath($path, $value)` to set a value into an array using a nested key\n  (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)\n* ServiceBuilders now support storing and retrieving arbitrary data\n* CachePlugin can now purge all resources for a given URI\n* CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource\n* CachePlugin now uses the Vary header to determine if a resource is a cache hit\n* `Guzzle\\Http\\Message\\Response` now implements `\\Serializable`\n* Added `Guzzle\\Cache\\CacheAdapterFactory::fromCache()` to more easily create cache adapters\n* `Guzzle\\Service\\ClientInterface::execute()` now accepts an array, single command, or Traversable\n* Fixed a bug in `Guzzle\\Http\\Message\\Header\\Link::addLink()`\n* Better handling of calculating the size of a stream in `Guzzle\\Stream\\Stream` using fstat() and caching the size\n* `Guzzle\\Common\\Exception\\ExceptionCollection` now creates a more readable exception message\n* Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older\n  Symfony users can still use the old version of Monolog.\n* Fixing BC break: Added the implementation back in for `Guzzle\\Http\\Message\\AbstractMessage::getTokenizedHeader()`.\n  Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.\n* Several performance improvements to `Guzzle\\Common\\Collection`\n* Added an `$options` argument to the end of the following methods of `Guzzle\\Http\\ClientInterface`:\n  createRequest, head, delete, put, patch, post, options, prepareRequest\n* Added an `$options` argument to the end of `Guzzle\\Http\\Message\\Request\\RequestFactoryInterface::createRequest()`\n* Added an `applyOptions()` method to `Guzzle\\Http\\Message\\Request\\RequestFactoryInterface`\n* Changed `Guzzle\\Http\\ClientInterface::get($uri = null, $headers = null, $body = null)` to\n  `Guzzle\\Http\\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a\n  resource, string, or EntityBody into the $options parameter to specify the download location of the response.\n* Changed `Guzzle\\Common\\Collection::__construct($data)` to no longer accepts a null value for `$data` but a\n  default `array()`\n* Added `Guzzle\\Stream\\StreamInterface::isRepeatable`\n* Removed `Guzzle\\Http\\ClientInterface::setDefaultHeaders(). Use\n  $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or\n  $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.\n* Removed `Guzzle\\Http\\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.\n* Removed `Guzzle\\Http\\ClientInterface::expandTemplate()`\n* Removed `Guzzle\\Http\\ClientInterface::setRequestFactory()`\n* Removed `Guzzle\\Http\\ClientInterface::getCurlMulti()`\n* Removed `Guzzle\\Http\\Message\\RequestInterface::canCache`\n* Removed `Guzzle\\Http\\Message\\RequestInterface::setIsRedirect`\n* Removed `Guzzle\\Http\\Message\\RequestInterface::isRedirect`\n* Made `Guzzle\\Http\\Client::expandTemplate` and `getUriTemplate` protected methods.\n* You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting\n  `Guzzle\\Common\\Version::$emitWarnings` to true.\n* Marked `Guzzle\\Http\\Message\\Request::isResponseBodyRepeatable()` as deprecated. Use\n      `$request->getResponseBody()->isRepeatable()` instead.\n* Marked `Guzzle\\Http\\Message\\Request::canCache()` as deprecated. Use\n  `Guzzle\\Plugin\\Cache\\DefaultCanCacheStrategy->canCacheRequest()` instead.\n* Marked `Guzzle\\Http\\Message\\Request::canCache()` as deprecated. Use\n  `Guzzle\\Plugin\\Cache\\DefaultCanCacheStrategy->canCacheRequest()` instead.\n* Marked `Guzzle\\Http\\Message\\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.\n* Marked `Guzzle\\Http\\Message\\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.\n* Marked `Guzzle\\Cache\\CacheAdapterFactory::factory()` as deprecated\n* Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.\n  These will work through Guzzle 4.0\n* Marked 'request.params' for `Guzzle\\Http\\Client` as deprecated. Use [request.options][params].\n* Marked `Guzzle\\Service\\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\\Service\\Client.\n* Marked `Guzzle\\Service\\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.\n* Marked `Guzzle\\Service\\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.\n* Marked `Guzzle\\Parser\\Url\\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.\n* Marked `Guzzle\\Common\\Collection::inject()` as deprecated.\n* Marked `Guzzle\\Plugin\\CurlAuth\\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');`\n* CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a\n  CacheStorageInterface. These two objects and interface will be removed in a future version.\n* Always setting X-cache headers on cached responses\n* Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin\n* `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface\n  $request, Response $response);`\n* `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`\n* `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`\n* Added `CacheStorageInterface::purge($url)`\n* `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin\n  $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,\n  CanCacheStrategyInterface $canCache = null)`\n* Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`\n\n## 3.6.0 - 2013-05-29\n\n* ServiceDescription now implements ToArrayInterface\n* Added command.hidden_params to blacklist certain headers from being treated as additionalParameters\n* Guzzle can now correctly parse incomplete URLs\n* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.\n* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution\n* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().\n* Specific header implementations can be created for complex headers. When a message creates a header, it uses a\n  HeaderFactory which can map specific headers to specific header classes. There is now a Link header and\n  CacheControl header implementation.\n* Removed from interface: Guzzle\\Http\\ClientInterface::setUriTemplate\n* Removed from interface: Guzzle\\Http\\ClientInterface::setCurlMulti()\n* Removed Guzzle\\Http\\Message\\Request::receivedRequestHeader() and implemented this functionality in\n  Guzzle\\Http\\Curl\\RequestMediator\n* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.\n* Removed the optional $tryChunkedTransfer option from Guzzle\\Http\\Message\\EntityEnclosingRequestInterface\n* Removed the $asObjects argument from Guzzle\\Http\\Message\\MessageInterface::getHeaders()\n* Removed Guzzle\\Parser\\ParserRegister::get(). Use getParser()\n* Removed Guzzle\\Parser\\ParserRegister::set(). Use registerParser().\n* All response header helper functions return a string rather than mixing Header objects and strings inconsistently\n* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle\n  directly via interfaces\n* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist\n  but are a no-op until removed.\n* Most classes that used to require a `Guzzle\\Service\\Command\\CommandInterface` typehint now request a\n  `Guzzle\\Service\\Command\\ArrayCommandInterface`.\n* Added `Guzzle\\Http\\Message\\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response\n  on a request while the request is still being transferred\n* The ability to case-insensitively search for header values\n* Guzzle\\Http\\Message\\Header::hasExactHeader\n* Guzzle\\Http\\Message\\Header::raw. Use getAll()\n* Deprecated cache control specific methods on Guzzle\\Http\\Message\\AbstractMessage. Use the CacheControl header object\n  instead.\n* `Guzzle\\Service\\Command\\CommandInterface` now extends from ToArrayInterface and ArrayAccess\n* Added the ability to cast Model objects to a string to view debug information.\n\n## 3.5.0 - 2013-05-13\n\n* Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times\n* Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove\n  itself from the EventDispatcher)\n* Bug: `Guzzle\\Log\\MessageFormatter` now properly writes \"total_time\" and \"connect_time\" values\n* Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too\n* Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a\n  non-existent key\n* Bug: All __call() method arguments are now required (helps with mocking frameworks)\n* Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference\n  to help with refcount based garbage collection of resources created by sending a request\n* Deprecating ZF1 cache and log adapters. These will be removed in the next major version.\n* Deprecating `Response::getPreviousResponse()` (method signature still exists, but it's deprecated). Use the\n  HistoryPlugin for a history.\n* Added a `responseBody` alias for the `response_body` location\n* Refactored internals to no longer rely on Response::getRequest()\n* HistoryPlugin can now be cast to a string\n* HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests\n  and responses that are sent over the wire\n* Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects\n\n## 3.4.3 - 2013-04-30\n\n* Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response\n* Added a check to re-extract the temp cacert bundle from the phar before sending each request\n\n## 3.4.2 - 2013-04-29\n\n* Bug fix: Stream objects now work correctly with \"a\" and \"a+\" modes\n* Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present\n* Bug fix: AsyncPlugin no longer forces HEAD requests\n* Bug fix: DateTime timezones are now properly handled when using the service description schema formatter\n* Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails\n* Setting a response on a request will write to the custom request body from the response body if one is specified\n* LogPlugin now writes to php://output when STDERR is undefined\n* Added the ability to set multiple POST files for the same key in a single call\n* application/x-www-form-urlencoded POSTs now use the utf-8 charset by default\n* Added the ability to queue CurlExceptions to the MockPlugin\n* Cleaned up how manual responses are queued on requests (removed \"queued_response\" and now using request.before_send)\n* Configuration loading now allows remote files\n\n## 3.4.1 - 2013-04-16\n\n* Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti\n  handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost.\n* Exceptions are now properly grouped when sending requests in parallel\n* Redirects are now properly aggregated when a multi transaction fails\n* Redirects now set the response on the original object even in the event of a failure\n* Bug fix: Model names are now properly set even when using $refs\n* Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax\n* Added support for oauth_callback in OAuth signatures\n* Added support for oauth_verifier in OAuth signatures\n* Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection\n\n## 3.4.0 - 2013-04-11\n\n* Bug fix: URLs are now resolved correctly based on https://tools.ietf.org/html/rfc3986#section-5.2. #289\n* Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289\n* Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263\n* Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.\n* Bug fix: Added `number` type to service descriptions.\n* Bug fix: empty parameters are removed from an OAuth signature\n* Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header\n* Bug fix: Fixed \"array to string\" error when validating a union of types in a service description\n* Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream\n* Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin.\n* Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs.\n* The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections.\n* Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if\n  the Content-Type can be determined based on the entity body or the path of the request.\n* Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder.\n* Added support for a PSR-3 LogAdapter.\n* Added a `command.after_prepare` event\n* Added `oauth_callback` parameter to the OauthPlugin\n* Added the ability to create a custom stream class when using a stream factory\n* Added a CachingEntityBody decorator\n* Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized.\n* The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar.\n* You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies\n* POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This\n  means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use\n  POST fields or files (the latter is only used when emulating a form POST in the browser).\n* Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest\n\n## 3.3.1 - 2013-03-10\n\n* Added the ability to create PHP streaming responses from HTTP requests\n* Bug fix: Running any filters when parsing response headers with service descriptions\n* Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing\n* Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across\n  response location visitors.\n* Bug fix: Removed the possibility of creating configuration files with circular dependencies\n* RequestFactory::create() now uses the key of a POST file when setting the POST file name\n* Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set\n\n## 3.3.0 - 2013-03-03\n\n* A large number of performance optimizations have been made\n* Bug fix: Added 'wb' as a valid write mode for streams\n* Bug fix: `Guzzle\\Http\\Message\\Response::json()` now allows scalar values to be returned\n* Bug fix: Fixed bug in `Guzzle\\Http\\Message\\Response` where wrapping quotes were stripped from `getEtag()`\n* BC: Removed `Guzzle\\Http\\Utils` class\n* BC: Setting a service description on a client will no longer modify the client's command factories.\n* BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using\n  the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'\n* BC: `Guzzle\\Stream\\Stream::getWrapper()` and `Guzzle\\Stream\\Stream::getSteamType()` are no longer converted to\n  lowercase\n* Operation parameter objects are now lazy loaded internally\n* Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses\n* Added support for instantiating responseType=class responseClass classes. Classes must implement\n  `Guzzle\\Service\\Command\\ResponseClassInterface`\n* Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These\n  additional properties also support locations and can be used to parse JSON responses where the outermost part of the\n  JSON is an array\n* Added support for nested renaming of JSON models (rename sentAs to name)\n* CachePlugin\n    * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error\n    * Debug headers can now added to cached response in the CachePlugin\n\n## 3.2.0 - 2013-02-14\n\n* CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients.\n* URLs with no path no longer contain a \"/\" by default\n* Guzzle\\Http\\QueryString does no longer manages the leading \"?\". This is now handled in Guzzle\\Http\\Url.\n* BadResponseException no longer includes the full request and response message\n* Adding setData() to Guzzle\\Service\\Description\\ServiceDescriptionInterface\n* Adding getResponseBody() to Guzzle\\Http\\Message\\RequestInterface\n* Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription\n* Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list\n* xmlEncoding can now be customized for the XML declaration of a XML service description operation\n* Guzzle\\Http\\QueryString now uses Guzzle\\Http\\QueryAggregator\\QueryAggregatorInterface objects to add custom value\n  aggregation and no longer uses callbacks\n* The URL encoding implementation of Guzzle\\Http\\QueryString can now be customized\n* Bug fix: Filters were not always invoked for array service description parameters\n* Bug fix: Redirects now use a target response body rather than a temporary response body\n* Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded\n* Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives\n\n## 3.1.2 - 2013-01-27\n\n* Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the\n  response body. For example, the XmlVisitor now parses the XML response into an array in the before() method.\n* Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent\n* CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444)\n* Fixed a bug where redirect responses were not chained correctly using getPreviousResponse()\n* Setting default headers on a client after setting the user-agent will not erase the user-agent setting\n\n## 3.1.1 - 2013-01-20\n\n* Adding wildcard support to Guzzle\\Common\\Collection::getPath()\n* Adding alias support to ServiceBuilder configs\n* Adding Guzzle\\Service\\Resource\\CompositeResourceIteratorFactory and cleaning up factory interface\n\n## 3.1.0 - 2013-01-12\n\n* BC: CurlException now extends from RequestException rather than BadResponseException\n* BC: Renamed Guzzle\\Plugin\\Cache\\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse()\n* Added getData to ServiceDescriptionInterface\n* Added context array to RequestInterface::setState()\n* Bug: Removing hard dependency on the BackoffPlugin from Guzzle\\Http\n* Bug: Adding required content-type when JSON request visitor adds JSON to a command\n* Bug: Fixing the serialization of a service description with custom data\n* Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing\n  an array of successful and failed responses\n* Moved getPath from Guzzle\\Service\\Resource\\Model to Guzzle\\Common\\Collection\n* Added Guzzle\\Http\\IoEmittingEntityBody\n* Moved command filtration from validators to location visitors\n* Added `extends` attributes to service description parameters\n* Added getModels to ServiceDescriptionInterface\n\n## 3.0.7 - 2012-12-19\n\n* Fixing phar detection when forcing a cacert to system if null or true\n* Allowing filename to be passed to `Guzzle\\Http\\Message\\Request::setResponseBody()`\n* Cleaning up `Guzzle\\Common\\Collection::inject` method\n* Adding a response_body location to service descriptions\n\n## 3.0.6 - 2012-12-09\n\n* CurlMulti performance improvements\n* Adding setErrorResponses() to Operation\n* composer.json tweaks\n\n## 3.0.5 - 2012-11-18\n\n* Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin\n* Bug: Response body can now be a string containing \"0\"\n* Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert\n* Bug: QueryString::fromString now properly parses query string parameters that contain equal signs\n* Added support for XML attributes in service description responses\n* DefaultRequestSerializer now supports array URI parameter values for URI template expansion\n* Added better mimetype guessing to requests and post files\n\n## 3.0.4 - 2012-11-11\n\n* Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value\n* Bug: Cookies can now be added that have a name, domain, or value set to \"0\"\n* Bug: Using the system cacert bundle when using the Phar\n* Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures\n* Enhanced cookie jar de-duplication\n* Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added\n* Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies\n* Added the ability to create any sort of hash for a stream rather than just an MD5 hash\n\n## 3.0.3 - 2012-11-04\n\n* Implementing redirects in PHP rather than cURL\n* Added PECL URI template extension and using as default parser if available\n* Bug: Fixed Content-Length parsing of Response factory\n* Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams.\n* Adding ToArrayInterface throughout library\n* Fixing OauthPlugin to create unique nonce values per request\n\n## 3.0.2 - 2012-10-25\n\n* Magic methods are enabled by default on clients\n* Magic methods return the result of a command\n* Service clients no longer require a base_url option in the factory\n* Bug: Fixed an issue with URI templates where null template variables were being expanded\n\n## 3.0.1 - 2012-10-22\n\n* Models can now be used like regular collection objects by calling filter, map, etc.\n* Models no longer require a Parameter structure or initial data in the constructor\n* Added a custom AppendIterator to get around a PHP bug with the `\\AppendIterator`\n\n## 3.0.0 - 2012-10-15\n\n* Rewrote service description format to be based on Swagger\n    * Now based on JSON schema\n    * Added nested input structures and nested response models\n    * Support for JSON and XML input and output models\n    * Renamed `commands` to `operations`\n    * Removed dot class notation\n    * Removed custom types\n* Broke the project into smaller top-level namespaces to be more component friendly\n* Removed support for XML configs and descriptions. Use arrays or JSON files.\n* Removed the Validation component and Inspector\n* Moved all cookie code to Guzzle\\Plugin\\Cookie\n* Magic methods on a Guzzle\\Service\\Client now return the command un-executed.\n* Calling getResult() or getResponse() on a command will lazily execute the command if needed.\n* Now shipping with cURL's CA certs and using it by default\n* Added previousResponse() method to response objects\n* No longer sending Accept and Accept-Encoding headers on every request\n* Only sending an Expect header by default when a payload is greater than 1MB\n* Added/moved client options:\n    * curl.blacklist to curl.option.blacklist\n    * Added ssl.certificate_authority\n* Added a Guzzle\\Iterator component\n* Moved plugins from Guzzle\\Http\\Plugin to Guzzle\\Plugin\n* Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin)\n* Added a more robust caching plugin\n* Added setBody to response objects\n* Updating LogPlugin to use a more flexible MessageFormatter\n* Added a completely revamped build process\n* Cleaning up Collection class and removing default values from the get method\n* Fixed ZF2 cache adapters\n\n## 2.8.8 - 2012-10-15\n\n* Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did\n\n## 2.8.7 - 2012-09-30\n\n* Bug: Fixed config file aliases for JSON includes\n* Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests\n* Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload\n* Bug: Hardening request and response parsing to account for missing parts\n* Bug: Fixed PEAR packaging\n* Bug: Fixed Request::getInfo\n* Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail\n* Adding the ability for the namespace Iterator factory to look in multiple directories\n* Added more getters/setters/removers from service descriptions\n* Added the ability to remove POST fields from OAuth signatures\n* OAuth plugin now supports 2-legged OAuth\n\n## 2.8.6 - 2012-09-05\n\n* Added the ability to modify and build service descriptions\n* Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command\n* Added a `json` parameter location\n* Now allowing dot notation for classes in the CacheAdapterFactory\n* Using the union of two arrays rather than an array_merge when extending service builder services and service params\n* Ensuring that a service is a string before doing strpos() checks on it when substituting services for references\n  in service builder config files.\n* Services defined in two different config files that include one another will by default replace the previously\n  defined service, but you can now create services that extend themselves and merge their settings over the previous\n* The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like\n  '_default' with a default JSON configuration file.\n\n## 2.8.5 - 2012-08-29\n\n* Bug: Suppressed empty arrays from URI templates\n* Bug: Added the missing $options argument from ServiceDescription::factory to enable caching\n* Added support for HTTP responses that do not contain a reason phrase in the start-line\n* AbstractCommand commands are now invokable\n* Added a way to get the data used when signing an Oauth request before a request is sent\n\n## 2.8.4 - 2012-08-15\n\n* Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin\n* Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable.\n* Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\\Common\\Stream\n* Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream\n* Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5())\n* Added additional response status codes\n* Removed SSL information from the default User-Agent header\n* DELETE requests can now send an entity body\n* Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries\n* Added the ability of the MockPlugin to consume mocked request bodies\n* LogPlugin now exposes request and response objects in the extras array\n\n## 2.8.3 - 2012-07-30\n\n* Bug: Fixed a case where empty POST requests were sent as GET requests\n* Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body\n* Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new\n* Added multiple inheritance to service description commands\n* Added an ApiCommandInterface and added `getParamNames()` and `hasParam()`\n* Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything\n* Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles\n\n## 2.8.2 - 2012-07-24\n\n* Bug: Query string values set to 0 are no longer dropped from the query string\n* Bug: A Collection object is no longer created each time a call is made to `Guzzle\\Service\\Command\\AbstractCommand::getRequestHeaders()`\n* Bug: `+` is now treated as an encoded space when parsing query strings\n* QueryString and Collection performance improvements\n* Allowing dot notation for class paths in filters attribute of a service descriptions\n\n## 2.8.1 - 2012-07-16\n\n* Loosening Event Dispatcher dependency\n* POST redirects can now be customized using CURLOPT_POSTREDIR\n\n## 2.8.0 - 2012-07-15\n\n* BC: Guzzle\\Http\\Query\n    * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl)\n    * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding()\n    * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool)\n    * Changed the aggregation functions of QueryString to be static methods\n    * Can now use fromString() with querystrings that have a leading ?\n* cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters\n* Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body\n* Cookies are no longer URL decoded by default\n* Bug: URI template variables set to null are no longer expanded\n\n## 2.7.2 - 2012-07-02\n\n* BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\\Http\\Parser to Guzzle\\Parser.\n* BC: Removing Guzzle\\Common\\Batch\\Batch::count() and replacing it with isEmpty()\n* CachePlugin now allows for a custom request parameter function to check if a request can be cached\n* Bug fix: CachePlugin now only caches GET and HEAD requests by default\n* Bug fix: Using header glue when transferring headers over the wire\n* Allowing deeply nested arrays for composite variables in URI templates\n* Batch divisors can now return iterators or arrays\n\n## 2.7.1 - 2012-06-26\n\n* Minor patch to update version number in UA string\n* Updating build process\n\n## 2.7.0 - 2012-06-25\n\n* BC: Inflection classes moved to Guzzle\\Inflection. No longer static methods. Can now inject custom inflectors into classes.\n* BC: Removed magic setX methods from commands\n* BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method\n* Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable.\n* Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity)\n* Guzzle\\Service\\Resource\\ResourceIteratorApplyBatched now internally uses the Guzzle\\Common\\Batch namespace\n* Added Guzzle\\Service\\Plugin namespace and a PluginCollectionPlugin\n* Added the ability to set POST fields and files in a service description\n* Guzzle\\Http\\EntityBody::factory() now accepts objects with a __toString() method\n* Adding a command.before_prepare event to clients\n* Added BatchClosureTransfer and BatchClosureDivisor\n* BatchTransferException now includes references to the batch divisor and transfer strategies\n* Fixed some tests so that they pass more reliably\n* Added Guzzle\\Common\\Log\\ArrayLogAdapter\n\n## 2.6.6 - 2012-06-10\n\n* BC: Removing Guzzle\\Http\\Plugin\\BatchQueuePlugin\n* BC: Removing Guzzle\\Service\\Command\\CommandSet\n* Adding generic batching system (replaces the batch queue plugin and command set)\n* Updating ZF cache and log adapters and now using ZF's composer repository\n* Bug: Setting the name of each ApiParam when creating through an ApiCommand\n* Adding result_type, result_doc, deprecated, and doc_url to service descriptions\n* Bug: Changed the default cookie header casing back to 'Cookie'\n\n## 2.6.5 - 2012-06-03\n\n* BC: Renaming Guzzle\\Http\\Message\\RequestInterface::getResourceUri() to getResource()\n* BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from\n* BC: Guzzle\\Http\\Cookie is now used to manage Set-Cookie data, not Cookie data\n* BC: Renaming methods in the CookieJarInterface\n* Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations\n* Making the default glue for HTTP headers ';' instead of ','\n* Adding a removeValue to Guzzle\\Http\\Message\\Header\n* Adding getCookies() to request interface.\n* Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber()\n\n## 2.6.4 - 2012-05-30\n\n* BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.\n* BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand\n* Bug: Fixing magic method command calls on clients\n* Bug: Email constraint only validates strings\n* Bug: Aggregate POST fields when POST files are present in curl handle\n* Bug: Fixing default User-Agent header\n* Bug: Only appending or prepending parameters in commands if they are specified\n* Bug: Not requiring response reason phrases or status codes to match a predefined list of codes\n* Allowing the use of dot notation for class namespaces when using instance_of constraint\n* Added any_match validation constraint\n* Added an AsyncPlugin\n* Passing request object to the calculateWait method of the ExponentialBackoffPlugin\n* Allowing the result of a command object to be changed\n* Parsing location and type sub values when instantiating a service description rather than over and over at runtime\n\n## 2.6.3 - 2012-05-23\n\n* [BC] Guzzle\\Common\\FromConfigInterface no longer requires any config options.\n* [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.\n* You can now use an array of data when creating PUT request bodies in the request factory.\n* Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.\n* [Http] Adding support for Content-Type in multipart POST uploads per upload\n* [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])\n* Adding more POST data operations for easier manipulation of POST data.\n* You can now set empty POST fields.\n* The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.\n* Split the Guzzle\\Service\\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.\n* CS updates\n\n## 2.6.2 - 2012-05-19\n\n* [Http] Better handling of nested scope requests in CurlMulti.  Requests are now always prepares in the send() method rather than the addRequest() method.\n\n## 2.6.1 - 2012-05-19\n\n* [BC] Removing 'path' support in service descriptions.  Use 'uri'.\n* [BC] Guzzle\\Service\\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.\n* [BC] Removing Guzzle\\Common\\NullObject.  Use https://github.com/mtdowling/NullObject if you need it.\n* [BC] Removing Guzzle\\Common\\XmlElement.\n* All commands, both dynamic and concrete, have ApiCommand objects.\n* Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.\n* Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.\n* Making the method signature of Guzzle\\Service\\Builder\\ServiceBuilder::factory more flexible.\n\n## 2.6.0 - 2012-05-15\n\n* [BC] Moving Guzzle\\Service\\Builder to Guzzle\\Service\\Builder\\ServiceBuilder\n* [BC] Executing a Command returns the result of the command rather than the command\n* [BC] Moving all HTTP parsing logic to Guzzle\\Http\\Parsers. Allows for faster C implementations if needed.\n* [BC] Changing the Guzzle\\Http\\Message\\Response::setProtocol() method to accept a protocol and version in separate args.\n* [BC] Moving ResourceIterator* to Guzzle\\Service\\Resource\n* [BC] Completely refactored ResourceIterators to iterate over a cloned command object\n* [BC] Moved Guzzle\\Http\\UriTemplate to Guzzle\\Http\\Parser\\UriTemplate\\UriTemplate\n* [BC] Guzzle\\Guzzle is now deprecated\n* Moving Guzzle\\Common\\Guzzle::inject to Guzzle\\Common\\Collection::inject\n* Adding Guzzle\\Version class to give version information about Guzzle\n* Adding Guzzle\\Http\\Utils class to provide getDefaultUserAgent() and getHttpDate()\n* Adding Guzzle\\Curl\\CurlVersion to manage caching curl_version() data\n* ServiceDescription and ServiceBuilder are now cacheable using similar configs\n* Changing the format of XML and JSON service builder configs.  Backwards compatible.\n* Cleaned up Cookie parsing\n* Trimming the default Guzzle User-Agent header\n* Adding a setOnComplete() method to Commands that is called when a command completes\n* Keeping track of requests that were mocked in the MockPlugin\n* Fixed a caching bug in the CacheAdapterFactory\n* Inspector objects can be injected into a Command object\n* Refactoring a lot of code and tests to be case insensitive when dealing with headers\n* Adding Guzzle\\Http\\Message\\HeaderComparison for easy comparison of HTTP headers using a DSL\n* Adding the ability to set global option overrides to service builder configs\n* Adding the ability to include other service builder config files from within XML and JSON files\n* Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.\n\n## 2.5.0 - 2012-05-08\n\n* Major performance improvements\n* [BC] Simplifying Guzzle\\Common\\Collection.  Please check to see if you are using features that are now deprecated.\n* [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.\n* [BC] No longer supporting \"{{ }}\" for injecting into command or UriTemplates.  Use \"{}\"\n* Added the ability to passed parameters to all requests created by a client\n* Added callback functionality to the ExponentialBackoffPlugin\n* Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies.\n* Rewinding request stream bodies when retrying requests\n* Exception is thrown when JSON response body cannot be decoded\n* Added configurable magic method calls to clients and commands.  This is off by default.\n* Fixed a defect that added a hash to every parsed URL part\n* Fixed duplicate none generation for OauthPlugin.\n* Emitting an event each time a client is generated by a ServiceBuilder\n* Using an ApiParams object instead of a Collection for parameters of an ApiCommand\n* cache.* request parameters should be renamed to params.cache.*\n* Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle.\n* Added the ability to disable type validation of service descriptions\n* ServiceDescriptions and ServiceBuilders are now Serializable\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2011 Michael Dowling <mtdowling@gmail.com>\nCopyright (c) 2012 Jeremy Lindblom <jeremeamia@gmail.com>\nCopyright (c) 2014 Graham Campbell <hello@gjcampbell.co.uk>\nCopyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com>\nCopyright (c) 2015 Tobias Schultze <webmaster@tubo-world.de>\nCopyright (c) 2016 Tobias Nyholm <tobias.nyholm@gmail.com>\nCopyright (c) 2016 George Mponos <gmponos@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/README.md",
    "content": "![Guzzle](.github/logo.png?raw=true)\n\n# Guzzle, PHP HTTP client\n\n[![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases)\n[![Build Status](https://img.shields.io/github/workflow/status/guzzle/guzzle/CI?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI)\n[![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle)\n\nGuzzle is a PHP HTTP client that makes it easy to send HTTP requests and\ntrivial to integrate with web services.\n\n- Simple interface for building query strings, POST requests, streaming large\n  uploads, streaming large downloads, using HTTP cookies, uploading JSON data,\n  etc...\n- Can send both synchronous and asynchronous requests using the same interface.\n- Uses PSR-7 interfaces for requests, responses, and streams. This allows you\n  to utilize other PSR-7 compatible libraries with Guzzle.\n- Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients.\n- Abstracts away the underlying HTTP transport, allowing you to write\n  environment and transport agnostic code; i.e., no hard dependency on cURL,\n  PHP streams, sockets, or non-blocking event loops.\n- Middleware system allows you to augment and compose client behavior.\n\n```php\n$client = new \\GuzzleHttp\\Client();\n$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');\n\necho $response->getStatusCode(); // 200\necho $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'\necho $response->getBody(); // '{\"id\": 1420053, \"name\": \"guzzle\", ...}'\n\n// Send an asynchronous request.\n$request = new \\GuzzleHttp\\Psr7\\Request('GET', 'http://httpbin.org');\n$promise = $client->sendAsync($request)->then(function ($response) {\n    echo 'I completed! ' . $response->getBody();\n});\n\n$promise->wait();\n```\n\n## Help and docs\n\nWe use GitHub issues only to discuss bugs and new features. For support please refer to:\n\n- [Documentation](http://guzzlephp.org/)\n- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle)\n- [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](http://slack.httplug.io/)\n- [Gitter](https://gitter.im/guzzle/guzzle)\n\n\n## Installing Guzzle\n\nThe recommended way to install Guzzle is through\n[Composer](https://getcomposer.org/).\n\n```bash\ncomposer require guzzlehttp/guzzle\n```\n\n\n## Version Guidance\n\n| Version | Status     | Packagist           | Namespace    | Repo                | Docs                | PSR-7 | PHP Version |\n|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------|\n| 3.x     | EOL        | `guzzle/guzzle`     | `Guzzle`     | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No    | >= 5.3.3    |\n| 4.x     | EOL        | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A                 | No    | >= 5.4      |\n| 5.x     | EOL        | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No    | >= 5.4      |\n| 6.x     | Security fixes | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes   | >= 5.5      |\n| 7.x     | Latest     | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes   | >= 7.2      |\n\n[guzzle-3-repo]: https://github.com/guzzle/guzzle3\n[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x\n[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3\n[guzzle-6-repo]: https://github.com/guzzle/guzzle/tree/6.5\n[guzzle-7-repo]: https://github.com/guzzle/guzzle\n[guzzle-3-docs]: http://guzzle3.readthedocs.org\n[guzzle-5-docs]: http://docs.guzzlephp.org/en/5.3/\n[guzzle-6-docs]: http://docs.guzzlephp.org/en/6.5/\n[guzzle-7-docs]: http://docs.guzzlephp.org/en/latest/\n\n\n## Security\n\nIf you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/guzzle/security/policy) for more information.\n\n## License\n\nGuzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.\n\n## For Enterprise\n\nAvailable as part of the Tidelift Subscription\n\nThe maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-guzzle?utm_source=packagist-guzzlehttp-guzzle&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/UPGRADING.md",
    "content": "Guzzle Upgrade Guide\n====================\n\n6.0 to 7.0\n----------\n\nIn order to take advantage of the new features of PHP, Guzzle dropped the support\nof PHP 5. The minimum supported PHP version is now PHP 7.2. Type hints and return\ntypes for functions and methods have been added wherever possible. \n\nPlease make sure:\n- You are calling a function or a method with the correct type.\n- If you extend a class of Guzzle; update all signatures on methods you override.\n\n#### Other backwards compatibility breaking changes\n\n- Class `GuzzleHttp\\UriTemplate` is removed.\n- Class `GuzzleHttp\\Exception\\SeekException` is removed.\n- Classes `GuzzleHttp\\Exception\\BadResponseException`, `GuzzleHttp\\Exception\\ClientException`, \n  `GuzzleHttp\\Exception\\ServerException` can no longer be initialized with an empty\n  Response as argument.\n- Class `GuzzleHttp\\Exception\\ConnectException` now extends `GuzzleHttp\\Exception\\TransferException`\n  instead of `GuzzleHttp\\Exception\\RequestException`.\n- Function `GuzzleHttp\\Exception\\ConnectException::getResponse()` is removed.\n- Function `GuzzleHttp\\Exception\\ConnectException::hasResponse()` is removed.\n- Constant `GuzzleHttp\\ClientInterface::VERSION` is removed. Added `GuzzleHttp\\ClientInterface::MAJOR_VERSION` instead.\n- Function `GuzzleHttp\\Exception\\RequestException::getResponseBodySummary` is removed.\n  Use `\\GuzzleHttp\\Psr7\\get_message_body_summary` as an alternative.\n- Function `GuzzleHttp\\Cookie\\CookieJar::getCookieValue` is removed.\n- Request option `exception` is removed. Please use `http_errors`.\n- Request option `save_to` is removed. Please use `sink`.\n- Pool option `pool_size` is removed. Please use `concurrency`.\n- We now look for environment variables in the `$_SERVER` super global, due to thread safety issues with `getenv`. We continue to fallback to `getenv` in CLI environments, for maximum compatibility.\n- The `get`, `head`, `put`, `post`, `patch`, `delete`, `getAsync`, `headAsync`, `putAsync`, `postAsync`, `patchAsync`, and `deleteAsync` methods are now implemented as genuine methods on `GuzzleHttp\\Client`, with strong typing. The original `__call` implementation remains unchanged for now, for maximum backwards compatibility, but won't be invoked under normal operation.\n- The `log` middleware will log the errors with level `error` instead of `notice` \n- Support for international domain names (IDN) is now disabled by default, and enabling it requires installing ext-intl, linked against a modern version of the C library (ICU 4.6 or higher).\n\n#### Native functions calls\n\nAll internal native functions calls of Guzzle are now prefixed with a slash. This\nchange makes it impossible for method overloading by other libraries or applications.\nExample:\n\n```php\n// Before:\ncurl_version();\n\n// After:\n\\curl_version();\n```\n\nFor the full diff you can check [here](https://github.com/guzzle/guzzle/compare/6.5.4..master).\n\n5.0 to 6.0\n----------\n\nGuzzle now uses [PSR-7](https://www.php-fig.org/psr/psr-7/) for HTTP messages.\nDue to the fact that these messages are immutable, this prompted a refactoring\nof Guzzle to use a middleware based system rather than an event system. Any\nHTTP message interaction (e.g., `GuzzleHttp\\Message\\Request`) need to be\nupdated to work with the new immutable PSR-7 request and response objects. Any\nevent listeners or subscribers need to be updated to become middleware\nfunctions that wrap handlers (or are injected into a\n`GuzzleHttp\\HandlerStack`).\n\n- Removed `GuzzleHttp\\BatchResults`\n- Removed `GuzzleHttp\\Collection`\n- Removed `GuzzleHttp\\HasDataTrait`\n- Removed `GuzzleHttp\\ToArrayInterface`\n- The `guzzlehttp/streams` dependency has been removed. Stream functionality\n  is now present in the `GuzzleHttp\\Psr7` namespace provided by the\n  `guzzlehttp/psr7` package.\n- Guzzle no longer uses ReactPHP promises and now uses the\n  `guzzlehttp/promises` library. We use a custom promise library for three\n  significant reasons:\n  1. React promises (at the time of writing this) are recursive. Promise\n     chaining and promise resolution will eventually blow the stack. Guzzle\n     promises are not recursive as they use a sort of trampolining technique.\n     Note: there has been movement in the React project to modify promises to\n     no longer utilize recursion.\n  2. Guzzle needs to have the ability to synchronously block on a promise to\n     wait for a result. Guzzle promises allows this functionality (and does\n     not require the use of recursion).\n  3. Because we need to be able to wait on a result, doing so using React\n     promises requires wrapping react promises with RingPHP futures. This\n     overhead is no longer needed, reducing stack sizes, reducing complexity,\n     and improving performance.\n- `GuzzleHttp\\Mimetypes` has been moved to a function in\n  `GuzzleHttp\\Psr7\\mimetype_from_extension` and\n  `GuzzleHttp\\Psr7\\mimetype_from_filename`.\n- `GuzzleHttp\\Query` and `GuzzleHttp\\QueryParser` have been removed. Query\n  strings must now be passed into request objects as strings, or provided to\n  the `query` request option when creating requests with clients. The `query`\n  option uses PHP's `http_build_query` to convert an array to a string. If you\n  need a different serialization technique, you will need to pass the query\n  string in as a string. There are a couple helper functions that will make\n  working with query strings easier: `GuzzleHttp\\Psr7\\parse_query` and\n  `GuzzleHttp\\Psr7\\build_query`.\n- Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware\n  system based on PSR-7, using RingPHP and it's middleware system as well adds\n  more complexity than the benefits it provides. All HTTP handlers that were\n  present in RingPHP have been modified to work directly with PSR-7 messages\n  and placed in the `GuzzleHttp\\Handler` namespace. This significantly reduces\n  complexity in Guzzle, removes a dependency, and improves performance. RingPHP\n  will be maintained for Guzzle 5 support, but will no longer be a part of\n  Guzzle 6.\n- As Guzzle now uses a middleware based systems the event system and RingPHP\n  integration has been removed. Note: while the event system has been removed,\n  it is possible to add your own type of event system that is powered by the\n  middleware system.\n  - Removed the `Event` namespace.\n  - Removed the `Subscriber` namespace.\n  - Removed `Transaction` class\n  - Removed `RequestFsm`\n  - Removed `RingBridge`\n  - `GuzzleHttp\\Subscriber\\Cookie` is now provided by\n    `GuzzleHttp\\Middleware::cookies`\n  - `GuzzleHttp\\Subscriber\\HttpError` is now provided by\n    `GuzzleHttp\\Middleware::httpError`\n  - `GuzzleHttp\\Subscriber\\History` is now provided by\n    `GuzzleHttp\\Middleware::history`\n  - `GuzzleHttp\\Subscriber\\Mock` is now provided by\n    `GuzzleHttp\\Handler\\MockHandler`\n  - `GuzzleHttp\\Subscriber\\Prepare` is now provided by\n    `GuzzleHttp\\PrepareBodyMiddleware`\n  - `GuzzleHttp\\Subscriber\\Redirect` is now provided by\n    `GuzzleHttp\\RedirectMiddleware`\n- Guzzle now uses `Psr\\Http\\Message\\UriInterface` (implements in\n  `GuzzleHttp\\Psr7\\Uri`) for URI support. `GuzzleHttp\\Url` is now gone.\n- Static functions in `GuzzleHttp\\Utils` have been moved to namespaced\n  functions under the `GuzzleHttp` namespace. This requires either a Composer\n  based autoloader or you to include functions.php.\n- `GuzzleHttp\\ClientInterface::getDefaultOption` has been renamed to\n  `GuzzleHttp\\ClientInterface::getConfig`.\n- `GuzzleHttp\\ClientInterface::setDefaultOption` has been removed.\n- The `json` and `xml` methods of response objects has been removed. With the\n  migration to strictly adhering to PSR-7 as the interface for Guzzle messages,\n  adding methods to message interfaces would actually require Guzzle messages\n  to extend from PSR-7 messages rather then work with them directly.\n\n## Migrating to middleware\n\nThe change to PSR-7 unfortunately required significant refactoring to Guzzle\ndue to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event\nsystem from plugins. The event system relied on mutability of HTTP messages and\nside effects in order to work. With immutable messages, you have to change your\nworkflow to become more about either returning a value (e.g., functional\nmiddlewares) or setting a value on an object. Guzzle v6 has chosen the\nfunctional middleware approach.\n\nInstead of using the event system to listen for things like the `before` event,\nyou now create a stack based middleware function that intercepts a request on\nthe way in and the promise of the response on the way out. This is a much\nsimpler and more predictable approach than the event system and works nicely\nwith PSR-7 middleware. Due to the use of promises, the middleware system is\nalso asynchronous.\n\nv5:\n\n```php\nuse GuzzleHttp\\Event\\BeforeEvent;\n$client = new GuzzleHttp\\Client();\n// Get the emitter and listen to the before event.\n$client->getEmitter()->on('before', function (BeforeEvent $e) {\n    // Guzzle v5 events relied on mutation\n    $e->getRequest()->setHeader('X-Foo', 'Bar');\n});\n```\n\nv6:\n\nIn v6, you can modify the request before it is sent using the `mapRequest`\nmiddleware. The idiomatic way in v6 to modify the request/response lifecycle is\nto setup a handler middleware stack up front and inject the handler into a\nclient.\n\n```php\nuse GuzzleHttp\\Middleware;\n// Create a handler stack that has all of the default middlewares attached\n$handler = GuzzleHttp\\HandlerStack::create();\n// Push the handler onto the handler stack\n$handler->push(Middleware::mapRequest(function (RequestInterface $request) {\n    // Notice that we have to return a request object\n    return $request->withHeader('X-Foo', 'Bar');\n}));\n// Inject the handler into the client\n$client = new GuzzleHttp\\Client(['handler' => $handler]);\n```\n\n## POST Requests\n\nThis version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params)\nand `multipart` request options. `form_params` is an associative array of\nstrings or array of strings and is used to serialize an\n`application/x-www-form-urlencoded` POST request. The\n[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart)\noption is now used to send a multipart/form-data POST request.\n\n`GuzzleHttp\\Post\\PostFile` has been removed. Use the `multipart` option to add\nPOST files to a multipart/form-data request.\n\nThe `body` option no longer accepts an array to send POST requests. Please use\n`multipart` or `form_params` instead.\n\nThe `base_url` option has been renamed to `base_uri`.\n\n4.x to 5.0\n----------\n\n## Rewritten Adapter Layer\n\nGuzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send\nHTTP requests. The `adapter` option in a `GuzzleHttp\\Client` constructor\nis still supported, but it has now been renamed to `handler`. Instead of\npassing a `GuzzleHttp\\Adapter\\AdapterInterface`, you must now pass a PHP\n`callable` that follows the RingPHP specification.\n\n## Removed Fluent Interfaces\n\n[Fluent interfaces were removed](https://ocramius.github.io/blog/fluent-interfaces-are-evil/)\nfrom the following classes:\n\n- `GuzzleHttp\\Collection`\n- `GuzzleHttp\\Url`\n- `GuzzleHttp\\Query`\n- `GuzzleHttp\\Post\\PostBody`\n- `GuzzleHttp\\Cookie\\SetCookie`\n\n## Removed functions.php\n\nRemoved \"functions.php\", so that Guzzle is truly PSR-4 compliant. The following\nfunctions can be used as replacements.\n\n- `GuzzleHttp\\json_decode` -> `GuzzleHttp\\Utils::jsonDecode`\n- `GuzzleHttp\\get_path` -> `GuzzleHttp\\Utils::getPath`\n- `GuzzleHttp\\Utils::setPath` -> `GuzzleHttp\\set_path`\n- `GuzzleHttp\\Pool::batch` -> `GuzzleHttp\\batch`. This function is, however,\n  deprecated in favor of using `GuzzleHttp\\Pool::batch()`.\n\nThe \"procedural\" global client has been removed with no replacement (e.g.,\n`GuzzleHttp\\get()`, `GuzzleHttp\\post()`, etc.). Use a `GuzzleHttp\\Client`\nobject as a replacement.\n\n## `throwImmediately` has been removed\n\nThe concept of \"throwImmediately\" has been removed from exceptions and error\nevents. This control mechanism was used to stop a transfer of concurrent\nrequests from completing. This can now be handled by throwing the exception or\nby cancelling a pool of requests or each outstanding future request\nindividually.\n\n## headers event has been removed\n\nRemoved the \"headers\" event. This event was only useful for changing the\nbody a response once the headers of the response were known. You can implement\na similar behavior in a number of ways. One example might be to use a\nFnStream that has access to the transaction being sent. For example, when the\nfirst byte is written, you could check if the response headers match your\nexpectations, and if so, change the actual stream body that is being\nwritten to.\n\n## Updates to HTTP Messages\n\nRemoved the `asArray` parameter from\n`GuzzleHttp\\Message\\MessageInterface::getHeader`. If you want to get a header\nvalue as an array, then use the newly added `getHeaderAsArray()` method of\n`MessageInterface`. This change makes the Guzzle interfaces compatible with\nthe PSR-7 interfaces.\n\n3.x to 4.0\n----------\n\n## Overarching changes:\n\n- Now requires PHP 5.4 or greater.\n- No longer requires cURL to send requests.\n- Guzzle no longer wraps every exception it throws. Only exceptions that are\n  recoverable are now wrapped by Guzzle.\n- Various namespaces have been removed or renamed.\n- No longer requiring the Symfony EventDispatcher. A custom event dispatcher\n  based on the Symfony EventDispatcher is\n  now utilized in `GuzzleHttp\\Event\\EmitterInterface` (resulting in significant\n  speed and functionality improvements).\n\nChanges per Guzzle 3.x namespace are described below.\n\n## Batch\n\nThe `Guzzle\\Batch` namespace has been removed. This is best left to\nthird-parties to implement on top of Guzzle's core HTTP library.\n\n## Cache\n\nThe `Guzzle\\Cache` namespace has been removed. (Todo: No suitable replacement\nhas been implemented yet, but hoping to utilize a PSR cache interface).\n\n## Common\n\n- Removed all of the wrapped exceptions. It's better to use the standard PHP\n  library for unrecoverable exceptions.\n- `FromConfigInterface` has been removed.\n- `Guzzle\\Common\\Version` has been removed. The VERSION constant can be found\n  at `GuzzleHttp\\ClientInterface::VERSION`.\n\n### Collection\n\n- `getAll` has been removed. Use `toArray` to convert a collection to an array.\n- `inject` has been removed.\n- `keySearch` has been removed.\n- `getPath` no longer supports wildcard expressions. Use something better like\n  JMESPath for this.\n- `setPath` now supports appending to an existing array via the `[]` notation.\n\n### Events\n\nGuzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses\n`GuzzleHttp\\Event\\Emitter`.\n\n- `Symfony\\Component\\EventDispatcher\\EventDispatcherInterface` is replaced by\n  `GuzzleHttp\\Event\\EmitterInterface`.\n- `Symfony\\Component\\EventDispatcher\\EventDispatcher` is replaced by\n  `GuzzleHttp\\Event\\Emitter`.\n- `Symfony\\Component\\EventDispatcher\\Event` is replaced by\n  `GuzzleHttp\\Event\\Event`, and Guzzle now has an EventInterface in\n  `GuzzleHttp\\Event\\EventInterface`.\n- `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and\n  `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the\n  event emitter of a request, client, etc. now uses the `getEmitter` method\n  rather than the `getDispatcher` method.\n\n#### Emitter\n\n- Use the `once()` method to add a listener that automatically removes itself\n  the first time it is invoked.\n- Use the `listeners()` method to retrieve a list of event listeners rather than\n  the `getListeners()` method.\n- Use `emit()` instead of `dispatch()` to emit an event from an emitter.\n- Use `attach()` instead of `addSubscriber()` and `detach()` instead of\n  `removeSubscriber()`.\n\n```php\n$mock = new Mock();\n// 3.x\n$request->getEventDispatcher()->addSubscriber($mock);\n$request->getEventDispatcher()->removeSubscriber($mock);\n// 4.x\n$request->getEmitter()->attach($mock);\n$request->getEmitter()->detach($mock);\n```\n\nUse the `on()` method to add a listener rather than the `addListener()` method.\n\n```php\n// 3.x\n$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } );\n// 4.x\n$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } );\n```\n\n## Http\n\n### General changes\n\n- The cacert.pem certificate has been moved to `src/cacert.pem`.\n- Added the concept of adapters that are used to transfer requests over the\n  wire.\n- Simplified the event system.\n- Sending requests in parallel is still possible, but batching is no longer a\n  concept of the HTTP layer. Instead, you must use the `complete` and `error`\n  events to asynchronously manage parallel request transfers.\n- `Guzzle\\Http\\Url` has moved to `GuzzleHttp\\Url`.\n- `Guzzle\\Http\\QueryString` has moved to `GuzzleHttp\\Query`.\n- QueryAggregators have been rewritten so that they are simply callable\n  functions.\n- `GuzzleHttp\\StaticClient` has been removed. Use the functions provided in\n  `functions.php` for an easy to use static client instance.\n- Exceptions in `GuzzleHttp\\Exception` have been updated to all extend from\n  `GuzzleHttp\\Exception\\TransferException`.\n\n### Client\n\nCalling methods like `get()`, `post()`, `head()`, etc. no longer create and\nreturn a request, but rather creates a request, sends the request, and returns\nthe response.\n\n```php\n// 3.0\n$request = $client->get('/');\n$response = $request->send();\n\n// 4.0\n$response = $client->get('/');\n\n// or, to mirror the previous behavior\n$request = $client->createRequest('GET', '/');\n$response = $client->send($request);\n```\n\n`GuzzleHttp\\ClientInterface` has changed.\n\n- The `send` method no longer accepts more than one request. Use `sendAll` to\n  send multiple requests in parallel.\n- `setUserAgent()` has been removed. Use a default request option instead. You\n  could, for example, do something like:\n  `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`.\n- `setSslVerification()` has been removed. Use default request options instead,\n  like `$client->setConfig('defaults/verify', true)`.\n\n`GuzzleHttp\\Client` has changed.\n\n- The constructor now accepts only an associative array. You can include a\n  `base_url` string or array to use a URI template as the base URL of a client.\n  You can also specify a `defaults` key that is an associative array of default\n  request options. You can pass an `adapter` to use a custom adapter,\n  `batch_adapter` to use a custom adapter for sending requests in parallel, or\n  a `message_factory` to change the factory used to create HTTP requests and\n  responses.\n- The client no longer emits a `client.create_request` event.\n- Creating requests with a client no longer automatically utilize a URI\n  template. You must pass an array into a creational method (e.g.,\n  `createRequest`, `get`, `put`, etc.) in order to expand a URI template.\n\n### Messages\n\nMessages no longer have references to their counterparts (i.e., a request no\nlonger has a reference to it's response, and a response no loger has a\nreference to its request). This association is now managed through a\n`GuzzleHttp\\Adapter\\TransactionInterface` object. You can get references to\nthese transaction objects using request events that are emitted over the\nlifecycle of a request.\n\n#### Requests with a body\n\n- `GuzzleHttp\\Message\\EntityEnclosingRequest` and\n  `GuzzleHttp\\Message\\EntityEnclosingRequestInterface` have been removed. The\n  separation between requests that contain a body and requests that do not\n  contain a body has been removed, and now `GuzzleHttp\\Message\\RequestInterface`\n  handles both use cases.\n- Any method that previously accepts a `GuzzleHttp\\Response` object now accept a\n  `GuzzleHttp\\Message\\ResponseInterface`.\n- `GuzzleHttp\\Message\\RequestFactoryInterface` has been renamed to\n  `GuzzleHttp\\Message\\MessageFactoryInterface`. This interface is used to create\n  both requests and responses and is implemented in\n  `GuzzleHttp\\Message\\MessageFactory`.\n- POST field and file methods have been removed from the request object. You\n  must now use the methods made available to `GuzzleHttp\\Post\\PostBodyInterface`\n  to control the format of a POST body. Requests that are created using a\n  standard `GuzzleHttp\\Message\\MessageFactoryInterface` will automatically use\n  a `GuzzleHttp\\Post\\PostBody` body if the body was passed as an array or if\n  the method is POST and no body is provided.\n\n```php\n$request = $client->createRequest('POST', '/');\n$request->getBody()->setField('foo', 'bar');\n$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r')));\n```\n\n#### Headers\n\n- `GuzzleHttp\\Message\\Header` has been removed. Header values are now simply\n  represented by an array of values or as a string. Header values are returned\n  as a string by default when retrieving a header value from a message. You can\n  pass an optional argument of `true` to retrieve a header value as an array\n  of strings instead of a single concatenated string.\n- `GuzzleHttp\\PostFile` and `GuzzleHttp\\PostFileInterface` have been moved to\n  `GuzzleHttp\\Post`. This interface has been simplified and now allows the\n  addition of arbitrary headers.\n- Custom headers like `GuzzleHttp\\Message\\Header\\Link` have been removed. Most\n  of the custom headers are now handled separately in specific\n  subscribers/plugins, and `GuzzleHttp\\Message\\HeaderValues::parseParams()` has\n  been updated to properly handle headers that contain parameters (like the\n  `Link` header).\n\n#### Responses\n\n- `GuzzleHttp\\Message\\Response::getInfo()` and\n  `GuzzleHttp\\Message\\Response::setInfo()` have been removed. Use the event\n  system to retrieve this type of information.\n- `GuzzleHttp\\Message\\Response::getRawHeaders()` has been removed.\n- `GuzzleHttp\\Message\\Response::getMessage()` has been removed.\n- `GuzzleHttp\\Message\\Response::calculateAge()` and other cache specific\n  methods have moved to the CacheSubscriber.\n- Header specific helper functions like `getContentMd5()` have been removed.\n  Just use `getHeader('Content-MD5')` instead.\n- `GuzzleHttp\\Message\\Response::setRequest()` and\n  `GuzzleHttp\\Message\\Response::getRequest()` have been removed. Use the event\n  system to work with request and response objects as a transaction.\n- `GuzzleHttp\\Message\\Response::getRedirectCount()` has been removed. Use the\n  Redirect subscriber instead.\n- `GuzzleHttp\\Message\\Response::isSuccessful()` and other related methods have\n  been removed. Use `getStatusCode()` instead.\n\n#### Streaming responses\n\nStreaming requests can now be created by a client directly, returning a\n`GuzzleHttp\\Message\\ResponseInterface` object that contains a body stream\nreferencing an open PHP HTTP stream.\n\n```php\n// 3.0\nuse Guzzle\\Stream\\PhpStreamRequestFactory;\n$request = $client->get('/');\n$factory = new PhpStreamRequestFactory();\n$stream = $factory->fromRequest($request);\n$data = $stream->read(1024);\n\n// 4.0\n$response = $client->get('/', ['stream' => true]);\n// Read some data off of the stream in the response body\n$data = $response->getBody()->read(1024);\n```\n\n#### Redirects\n\nThe `configureRedirects()` method has been removed in favor of a\n`allow_redirects` request option.\n\n```php\n// Standard redirects with a default of a max of 5 redirects\n$request = $client->createRequest('GET', '/', ['allow_redirects' => true]);\n\n// Strict redirects with a custom number of redirects\n$request = $client->createRequest('GET', '/', [\n    'allow_redirects' => ['max' => 5, 'strict' => true]\n]);\n```\n\n#### EntityBody\n\nEntityBody interfaces and classes have been removed or moved to\n`GuzzleHttp\\Stream`. All classes and interfaces that once required\n`GuzzleHttp\\EntityBodyInterface` now require\n`GuzzleHttp\\Stream\\StreamInterface`. Creating a new body for a request no\nlonger uses `GuzzleHttp\\EntityBody::factory` but now uses\n`GuzzleHttp\\Stream\\Stream::factory` or even better:\n`GuzzleHttp\\Stream\\create()`.\n\n- `Guzzle\\Http\\EntityBodyInterface` is now `GuzzleHttp\\Stream\\StreamInterface`\n- `Guzzle\\Http\\EntityBody` is now `GuzzleHttp\\Stream\\Stream`\n- `Guzzle\\Http\\CachingEntityBody` is now `GuzzleHttp\\Stream\\CachingStream`\n- `Guzzle\\Http\\ReadLimitEntityBody` is now `GuzzleHttp\\Stream\\LimitStream`\n- `Guzzle\\Http\\IoEmittyinEntityBody` has been removed.\n\n#### Request lifecycle events\n\nRequests previously submitted a large number of requests. The number of events\nemitted over the lifecycle of a request has been significantly reduced to make\nit easier to understand how to extend the behavior of a request. All events\nemitted during the lifecycle of a request now emit a custom\n`GuzzleHttp\\Event\\EventInterface` object that contains context providing\nmethods and a way in which to modify the transaction at that specific point in\ntime (e.g., intercept the request and set a response on the transaction).\n\n- `request.before_send` has been renamed to `before` and now emits a\n  `GuzzleHttp\\Event\\BeforeEvent`\n- `request.complete` has been renamed to `complete` and now emits a\n  `GuzzleHttp\\Event\\CompleteEvent`.\n- `request.sent` has been removed. Use `complete`.\n- `request.success` has been removed. Use `complete`.\n- `error` is now an event that emits a `GuzzleHttp\\Event\\ErrorEvent`.\n- `request.exception` has been removed. Use `error`.\n- `request.receive.status_line` has been removed.\n- `curl.callback.progress` has been removed. Use a custom `StreamInterface` to\n  maintain a status update.\n- `curl.callback.write` has been removed. Use a custom `StreamInterface` to\n  intercept writes.\n- `curl.callback.read` has been removed. Use a custom `StreamInterface` to\n  intercept reads.\n\n`headers` is a new event that is emitted after the response headers of a\nrequest have been received before the body of the response is downloaded. This\nevent emits a `GuzzleHttp\\Event\\HeadersEvent`.\n\nYou can intercept a request and inject a response using the `intercept()` event\nof a `GuzzleHttp\\Event\\BeforeEvent`, `GuzzleHttp\\Event\\CompleteEvent`, and\n`GuzzleHttp\\Event\\ErrorEvent` event.\n\nSee: http://docs.guzzlephp.org/en/latest/events.html\n\n## Inflection\n\nThe `Guzzle\\Inflection` namespace has been removed. This is not a core concern\nof Guzzle.\n\n## Iterator\n\nThe `Guzzle\\Iterator` namespace has been removed.\n\n- `Guzzle\\Iterator\\AppendIterator`, `Guzzle\\Iterator\\ChunkedIterator`, and\n  `Guzzle\\Iterator\\MethodProxyIterator` are nice, but not a core requirement of\n  Guzzle itself.\n- `Guzzle\\Iterator\\FilterIterator` is no longer needed because an equivalent\n  class is shipped with PHP 5.4.\n- `Guzzle\\Iterator\\MapIterator` is not really needed when using PHP 5.5 because\n  it's easier to just wrap an iterator in a generator that maps values.\n\nFor a replacement of these iterators, see https://github.com/nikic/iter\n\n## Log\n\nThe LogPlugin has moved to https://github.com/guzzle/log-subscriber. The\n`Guzzle\\Log` namespace has been removed. Guzzle now relies on\n`Psr\\Log\\LoggerInterface` for all logging. The MessageFormatter class has been\nmoved to `GuzzleHttp\\Subscriber\\Log\\Formatter`.\n\n## Parser\n\nThe `Guzzle\\Parser` namespace has been removed. This was previously used to\nmake it possible to plug in custom parsers for cookies, messages, URI\ntemplates, and URLs; however, this level of complexity is not needed in Guzzle\nso it has been removed.\n\n- Cookie: Cookie parsing logic has been moved to\n  `GuzzleHttp\\Cookie\\SetCookie::fromString`.\n- Message: Message parsing logic for both requests and responses has been moved\n  to `GuzzleHttp\\Message\\MessageFactory::fromMessage`. Message parsing is only\n  used in debugging or deserializing messages, so it doesn't make sense for\n  Guzzle as a library to add this level of complexity to parsing messages.\n- UriTemplate: URI template parsing has been moved to\n  `GuzzleHttp\\UriTemplate`. The Guzzle library will automatically use the PECL\n  URI template library if it is installed.\n- Url: URL parsing is now performed in `GuzzleHttp\\Url::fromString` (previously\n  it was `Guzzle\\Http\\Url::factory()`). If custom URL parsing is necessary,\n  then developers are free to subclass `GuzzleHttp\\Url`.\n\n## Plugin\n\nThe `Guzzle\\Plugin` namespace has been renamed to `GuzzleHttp\\Subscriber`.\nSeveral plugins are shipping with the core Guzzle library under this namespace.\n\n- `GuzzleHttp\\Subscriber\\Cookie`: Replaces the old CookiePlugin. Cookie jar\n  code has moved to `GuzzleHttp\\Cookie`.\n- `GuzzleHttp\\Subscriber\\History`: Replaces the old HistoryPlugin.\n- `GuzzleHttp\\Subscriber\\HttpError`: Throws errors when a bad HTTP response is\n  received.\n- `GuzzleHttp\\Subscriber\\Mock`: Replaces the old MockPlugin.\n- `GuzzleHttp\\Subscriber\\Prepare`: Prepares the body of a request just before\n  sending. This subscriber is attached to all requests by default.\n- `GuzzleHttp\\Subscriber\\Redirect`: Replaces the RedirectPlugin.\n\nThe following plugins have been removed (third-parties are free to re-implement\nthese if needed):\n\n- `GuzzleHttp\\Plugin\\Async` has been removed.\n- `GuzzleHttp\\Plugin\\CurlAuth` has been removed.\n- `GuzzleHttp\\Plugin\\ErrorResponse\\ErrorResponsePlugin` has been removed. This\n  functionality should instead be implemented with event listeners that occur\n  after normal response parsing occurs in the guzzle/command package.\n\nThe following plugins are not part of the core Guzzle package, but are provided\nin separate repositories:\n\n- `Guzzle\\Http\\Plugin\\BackoffPlugin` has been rewritten to be much simpler\n  to build custom retry policies using simple functions rather than various\n  chained classes. See: https://github.com/guzzle/retry-subscriber\n- `Guzzle\\Http\\Plugin\\Cache\\CachePlugin` has moved to\n  https://github.com/guzzle/cache-subscriber\n- `Guzzle\\Http\\Plugin\\Log\\LogPlugin` has moved to\n  https://github.com/guzzle/log-subscriber\n- `Guzzle\\Http\\Plugin\\Md5\\Md5Plugin` has moved to\n  https://github.com/guzzle/message-integrity-subscriber\n- `Guzzle\\Http\\Plugin\\Mock\\MockPlugin` has moved to\n  `GuzzleHttp\\Subscriber\\MockSubscriber`.\n- `Guzzle\\Http\\Plugin\\Oauth\\OauthPlugin` has moved to\n  https://github.com/guzzle/oauth-subscriber\n\n## Service\n\nThe service description layer of Guzzle has moved into two separate packages:\n\n- http://github.com/guzzle/command Provides a high level abstraction over web\n  services by representing web service operations using commands.\n- http://github.com/guzzle/guzzle-services Provides an implementation of\n  guzzle/command that provides request serialization and response parsing using\n  Guzzle service descriptions.\n\n## Stream\n\nStream have moved to a separate package available at\nhttps://github.com/guzzle/streams.\n\n`Guzzle\\Stream\\StreamInterface` has been given a large update to cleanly take\non the responsibilities of `Guzzle\\Http\\EntityBody` and\n`Guzzle\\Http\\EntityBodyInterface` now that they have been removed. The number\nof methods implemented by the `StreamInterface` has been drastically reduced to\nallow developers to more easily extend and decorate stream behavior.\n\n## Removed methods from StreamInterface\n\n- `getStream` and `setStream` have been removed to better encapsulate streams.\n- `getMetadata` and `setMetadata` have been removed in favor of\n  `GuzzleHttp\\Stream\\MetadataStreamInterface`.\n- `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been\n  removed. This data is accessible when\n  using streams that implement `GuzzleHttp\\Stream\\MetadataStreamInterface`.\n- `rewind` has been removed. Use `seek(0)` for a similar behavior.\n\n## Renamed methods\n\n- `detachStream` has been renamed to `detach`.\n- `feof` has been renamed to `eof`.\n- `ftell` has been renamed to `tell`.\n- `readLine` has moved from an instance method to a static class method of\n  `GuzzleHttp\\Stream\\Stream`.\n\n## Metadata streams\n\n`GuzzleHttp\\Stream\\MetadataStreamInterface` has been added to denote streams\nthat contain additional metadata accessible via `getMetadata()`.\n`GuzzleHttp\\Stream\\StreamInterface::getMetadata` and\n`GuzzleHttp\\Stream\\StreamInterface::setMetadata` have been removed.\n\n## StreamRequestFactory\n\nThe entire concept of the StreamRequestFactory has been removed. The way this\nwas used in Guzzle 3 broke the actual interface of sending streaming requests\n(instead of getting back a Response, you got a StreamInterface). Streaming\nPHP requests are now implemented through the `GuzzleHttp\\Adapter\\StreamAdapter`.\n\n3.6 to 3.7\n----------\n\n### Deprecations\n\n- You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.:\n\n```php\n\\Guzzle\\Common\\Version::$emitWarnings = true;\n```\n\nThe following APIs and options have been marked as deprecated:\n\n- Marked `Guzzle\\Http\\Message\\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead.\n- Marked `Guzzle\\Http\\Message\\Request::canCache()` as deprecated. Use `Guzzle\\Plugin\\Cache\\DefaultCanCacheStrategy->canCacheRequest()` instead.\n- Marked `Guzzle\\Http\\Message\\Request::canCache()` as deprecated. Use `Guzzle\\Plugin\\Cache\\DefaultCanCacheStrategy->canCacheRequest()` instead.\n- Marked `Guzzle\\Http\\Message\\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.\n- Marked `Guzzle\\Http\\Message\\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.\n- Marked `Guzzle\\Cache\\CacheAdapterFactory::factory()` as deprecated\n- Marked `Guzzle\\Service\\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\\Service\\Client.\n- Marked `Guzzle\\Parser\\Url\\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.\n- Marked `Guzzle\\Common\\Collection::inject()` as deprecated.\n- Marked `Guzzle\\Plugin\\CurlAuth\\CurlAuthPlugin` as deprecated. Use\n  `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or\n  `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));`\n\n3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational\nrequest methods. When paired with a client's configuration settings, these options allow you to specify default settings\nfor various aspects of a request. Because these options make other previous configuration options redundant, several\nconfiguration options and methods of a client and AbstractCommand have been deprecated.\n\n- Marked `Guzzle\\Service\\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`.\n- Marked `Guzzle\\Service\\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`.\n- Marked 'request.params' for `Guzzle\\Http\\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')`\n- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0\n\n        $command = $client->getCommand('foo', array(\n            'command.headers' => array('Test' => '123'),\n            'command.response_body' => '/path/to/file'\n        ));\n\n        // Should be changed to:\n\n        $command = $client->getCommand('foo', array(\n            'command.request_options' => array(\n                'headers' => array('Test' => '123'),\n                'save_as' => '/path/to/file'\n            )\n        ));\n\n### Interface changes\n\nAdditions and changes (you will need to update any implementations or subclasses you may have created):\n\n- Added an `$options` argument to the end of the following methods of `Guzzle\\Http\\ClientInterface`:\n  createRequest, head, delete, put, patch, post, options, prepareRequest\n- Added an `$options` argument to the end of `Guzzle\\Http\\Message\\Request\\RequestFactoryInterface::createRequest()`\n- Added an `applyOptions()` method to `Guzzle\\Http\\Message\\Request\\RequestFactoryInterface`\n- Changed `Guzzle\\Http\\ClientInterface::get($uri = null, $headers = null, $body = null)` to\n  `Guzzle\\Http\\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a\n  resource, string, or EntityBody into the $options parameter to specify the download location of the response.\n- Changed `Guzzle\\Common\\Collection::__construct($data)` to no longer accepts a null value for `$data` but a\n  default `array()`\n- Added `Guzzle\\Stream\\StreamInterface::isRepeatable`\n- Made `Guzzle\\Http\\Client::expandTemplate` and `getUriTemplate` protected methods.\n\nThe following methods were removed from interfaces. All of these methods are still available in the concrete classes\nthat implement them, but you should update your code to use alternative methods:\n\n- Removed `Guzzle\\Http\\ClientInterface::setDefaultHeaders(). Use\n  `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or\n  `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or\n  `$client->setDefaultOption('headers/{header_name}', 'value')`. or\n  `$client->setDefaultOption('headers', array('header_name' => 'value'))`.\n- Removed `Guzzle\\Http\\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`.\n- Removed `Guzzle\\Http\\ClientInterface::expandTemplate()`. This is an implementation detail.\n- Removed `Guzzle\\Http\\ClientInterface::setRequestFactory()`. This is an implementation detail.\n- Removed `Guzzle\\Http\\ClientInterface::getCurlMulti()`. This is a very specific implementation detail.\n- Removed `Guzzle\\Http\\Message\\RequestInterface::canCache`. Use the CachePlugin.\n- Removed `Guzzle\\Http\\Message\\RequestInterface::setIsRedirect`. Use the HistoryPlugin.\n- Removed `Guzzle\\Http\\Message\\RequestInterface::isRedirect`. Use the HistoryPlugin.\n\n### Cache plugin breaking changes\n\n- CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a\n  CacheStorageInterface. These two objects and interface will be removed in a future version.\n- Always setting X-cache headers on cached responses\n- Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin\n- `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface\n  $request, Response $response);`\n- `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`\n- `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`\n- Added `CacheStorageInterface::purge($url)`\n- `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin\n  $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,\n  CanCacheStrategyInterface $canCache = null)`\n- Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`\n\n3.5 to 3.6\n----------\n\n* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.\n* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution\n* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().\n  For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader().\n  Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request.\n* Specific header implementations can be created for complex headers. When a message creates a header, it uses a\n  HeaderFactory which can map specific headers to specific header classes. There is now a Link header and\n  CacheControl header implementation.\n* Moved getLinks() from Response to just be used on a Link header object.\n\nIf you previously relied on Guzzle\\Http\\Message\\Header::raw(), then you will need to update your code to use the\nHeaderInterface (e.g. toArray(), getAll(), etc.).\n\n### Interface changes\n\n* Removed from interface: Guzzle\\Http\\ClientInterface::setUriTemplate\n* Removed from interface: Guzzle\\Http\\ClientInterface::setCurlMulti()\n* Removed Guzzle\\Http\\Message\\Request::receivedRequestHeader() and implemented this functionality in\n  Guzzle\\Http\\Curl\\RequestMediator\n* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.\n* Removed the optional $tryChunkedTransfer option from Guzzle\\Http\\Message\\EntityEnclosingRequestInterface\n* Removed the $asObjects argument from Guzzle\\Http\\Message\\MessageInterface::getHeaders()\n\n### Removed deprecated functions\n\n* Removed Guzzle\\Parser\\ParserRegister::get(). Use getParser()\n* Removed Guzzle\\Parser\\ParserRegister::set(). Use registerParser().\n\n### Deprecations\n\n* The ability to case-insensitively search for header values\n* Guzzle\\Http\\Message\\Header::hasExactHeader\n* Guzzle\\Http\\Message\\Header::raw. Use getAll()\n* Deprecated cache control specific methods on Guzzle\\Http\\Message\\AbstractMessage. Use the CacheControl header object\n  instead.\n\n### Other changes\n\n* All response header helper functions return a string rather than mixing Header objects and strings inconsistently\n* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle\n  directly via interfaces\n* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist\n  but are a no-op until removed.\n* Most classes that used to require a `Guzzle\\Service\\Command\\CommandInterface` typehint now request a\n  `Guzzle\\Service\\Command\\ArrayCommandInterface`.\n* Added `Guzzle\\Http\\Message\\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response\n  on a request while the request is still being transferred\n* `Guzzle\\Service\\Command\\CommandInterface` now extends from ToArrayInterface and ArrayAccess\n\n3.3 to 3.4\n----------\n\nBase URLs of a client now follow the rules of https://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.\n\n3.2 to 3.3\n----------\n\n### Response::getEtag() quote stripping removed\n\n`Guzzle\\Http\\Message\\Response::getEtag()` no longer strips quotes around the ETag response header\n\n### Removed `Guzzle\\Http\\Utils`\n\nThe `Guzzle\\Http\\Utils` class was removed. This class was only used for testing.\n\n### Stream wrapper and type\n\n`Guzzle\\Stream\\Stream::getWrapper()` and `Guzzle\\Stream\\Stream::getStreamType()` are no longer converted to lowercase.\n\n### curl.emit_io became emit_io\n\nEmitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the\n'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'\n\n3.1 to 3.2\n----------\n\n### CurlMulti is no longer reused globally\n\nBefore 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added\nto a single client can pollute requests dispatched from other clients.\n\nIf you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the\nServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is\ncreated.\n\n```php\n$multi = new Guzzle\\Http\\Curl\\CurlMulti();\n$builder = Guzzle\\Service\\Builder\\ServiceBuilder::factory('/path/to/config.json');\n$builder->addListener('service_builder.create_client', function ($event) use ($multi) {\n    $event['client']->setCurlMulti($multi);\n}\n});\n```\n\n### No default path\n\nURLs no longer have a default path value of '/' if no path was specified.\n\nBefore:\n\n```php\n$request = $client->get('http://www.foo.com');\necho $request->getUrl();\n// >> http://www.foo.com/\n```\n\nAfter:\n\n```php\n$request = $client->get('http://www.foo.com');\necho $request->getUrl();\n// >> http://www.foo.com\n```\n\n### Less verbose BadResponseException\n\nThe exception message for `Guzzle\\Http\\Exception\\BadResponseException` no longer contains the full HTTP request and\nresponse information. You can, however, get access to the request and response object by calling `getRequest()` or\n`getResponse()` on the exception object.\n\n### Query parameter aggregation\n\nMulti-valued query parameters are no longer aggregated using a callback function. `Guzzle\\Http\\Query` now has a\nsetAggregator() method that accepts a `Guzzle\\Http\\QueryAggregator\\QueryAggregatorInterface` object. This object is\nresponsible for handling the aggregation of multi-valued query string variables into a flattened hash.\n\n2.8 to 3.x\n----------\n\n### Guzzle\\Service\\Inspector\n\nChange `\\Guzzle\\Service\\Inspector::fromConfig` to `\\Guzzle\\Common\\Collection::fromConfig`\n\n**Before**\n\n```php\nuse Guzzle\\Service\\Inspector;\n\nclass YourClient extends \\Guzzle\\Service\\Client\n{\n    public static function factory($config = array())\n    {\n        $default = array();\n        $required = array('base_url', 'username', 'api_key');\n        $config = Inspector::fromConfig($config, $default, $required);\n\n        $client = new self(\n            $config->get('base_url'),\n            $config->get('username'),\n            $config->get('api_key')\n        );\n        $client->setConfig($config);\n\n        $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));\n\n        return $client;\n    }\n```\n\n**After**\n\n```php\nuse Guzzle\\Common\\Collection;\n\nclass YourClient extends \\Guzzle\\Service\\Client\n{\n    public static function factory($config = array())\n    {\n        $default = array();\n        $required = array('base_url', 'username', 'api_key');\n        $config = Collection::fromConfig($config, $default, $required);\n\n        $client = new self(\n            $config->get('base_url'),\n            $config->get('username'),\n            $config->get('api_key')\n        );\n        $client->setConfig($config);\n\n        $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));\n\n        return $client;\n    }\n```\n\n### Convert XML Service Descriptions to JSON\n\n**Before**\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<client>\n    <commands>\n        <!-- Groups -->\n        <command name=\"list_groups\" method=\"GET\" uri=\"groups.json\">\n            <doc>Get a list of groups</doc>\n        </command>\n        <command name=\"search_groups\" method=\"GET\" uri='search.json?query=\"{{query}} type:group\"'>\n            <doc>Uses a search query to get a list of groups</doc>\n            <param name=\"query\" type=\"string\" required=\"true\" />\n        </command>\n        <command name=\"create_group\" method=\"POST\" uri=\"groups.json\">\n            <doc>Create a group</doc>\n            <param name=\"data\" type=\"array\" location=\"body\" filters=\"json_encode\" doc=\"Group JSON\"/>\n            <param name=\"Content-Type\" location=\"header\" static=\"application/json\"/>\n        </command>\n        <command name=\"delete_group\" method=\"DELETE\" uri=\"groups/{{id}}.json\">\n            <doc>Delete a group by ID</doc>\n            <param name=\"id\" type=\"integer\" required=\"true\"/>\n        </command>\n        <command name=\"get_group\" method=\"GET\" uri=\"groups/{{id}}.json\">\n            <param name=\"id\" type=\"integer\" required=\"true\"/>\n        </command>\n        <command name=\"update_group\" method=\"PUT\" uri=\"groups/{{id}}.json\">\n            <doc>Update a group</doc>\n            <param name=\"id\" type=\"integer\" required=\"true\"/>\n            <param name=\"data\" type=\"array\" location=\"body\" filters=\"json_encode\" doc=\"Group JSON\"/>\n            <param name=\"Content-Type\" location=\"header\" static=\"application/json\"/>\n        </command>\n    </commands>\n</client>\n```\n\n**After**\n\n```json\n{\n    \"name\":       \"Zendesk REST API v2\",\n    \"apiVersion\": \"2012-12-31\",\n    \"description\":\"Provides access to Zendesk views, groups, tickets, ticket fields, and users\",\n    \"operations\": {\n        \"list_groups\":  {\n            \"httpMethod\":\"GET\",\n            \"uri\":       \"groups.json\",\n            \"summary\":   \"Get a list of groups\"\n        },\n        \"search_groups\":{\n            \"httpMethod\":\"GET\",\n            \"uri\":       \"search.json?query=\\\"{query} type:group\\\"\",\n            \"summary\":   \"Uses a search query to get a list of groups\",\n            \"parameters\":{\n                \"query\":{\n                    \"location\":   \"uri\",\n                    \"description\":\"Zendesk Search Query\",\n                    \"type\":       \"string\",\n                    \"required\":   true\n                }\n            }\n        },\n        \"create_group\": {\n            \"httpMethod\":\"POST\",\n            \"uri\":       \"groups.json\",\n            \"summary\":   \"Create a group\",\n            \"parameters\":{\n                \"data\":        {\n                    \"type\":       \"array\",\n                    \"location\":   \"body\",\n                    \"description\":\"Group JSON\",\n                    \"filters\":    \"json_encode\",\n                    \"required\":   true\n                },\n                \"Content-Type\":{\n                    \"type\":    \"string\",\n                    \"location\":\"header\",\n                    \"static\":  \"application/json\"\n                }\n            }\n        },\n        \"delete_group\": {\n            \"httpMethod\":\"DELETE\",\n            \"uri\":       \"groups/{id}.json\",\n            \"summary\":   \"Delete a group\",\n            \"parameters\":{\n                \"id\":{\n                    \"location\":   \"uri\",\n                    \"description\":\"Group to delete by ID\",\n                    \"type\":       \"integer\",\n                    \"required\":   true\n                }\n            }\n        },\n        \"get_group\":    {\n            \"httpMethod\":\"GET\",\n            \"uri\":       \"groups/{id}.json\",\n            \"summary\":   \"Get a ticket\",\n            \"parameters\":{\n                \"id\":{\n                    \"location\":   \"uri\",\n                    \"description\":\"Group to get by ID\",\n                    \"type\":       \"integer\",\n                    \"required\":   true\n                }\n            }\n        },\n        \"update_group\": {\n            \"httpMethod\":\"PUT\",\n            \"uri\":       \"groups/{id}.json\",\n            \"summary\":   \"Update a group\",\n            \"parameters\":{\n                \"id\":          {\n                    \"location\":   \"uri\",\n                    \"description\":\"Group to update by ID\",\n                    \"type\":       \"integer\",\n                    \"required\":   true\n                },\n                \"data\":        {\n                    \"type\":       \"array\",\n                    \"location\":   \"body\",\n                    \"description\":\"Group JSON\",\n                    \"filters\":    \"json_encode\",\n                    \"required\":   true\n                },\n                \"Content-Type\":{\n                    \"type\":    \"string\",\n                    \"location\":\"header\",\n                    \"static\":  \"application/json\"\n                }\n            }\n        }\n}\n```\n\n### Guzzle\\Service\\Description\\ServiceDescription\n\nCommands are now called Operations\n\n**Before**\n\n```php\nuse Guzzle\\Service\\Description\\ServiceDescription;\n\n$sd = new ServiceDescription();\n$sd->getCommands();     // @returns ApiCommandInterface[]\n$sd->hasCommand($name);\n$sd->getCommand($name); // @returns ApiCommandInterface|null\n$sd->addCommand($command); // @param ApiCommandInterface $command\n```\n\n**After**\n\n```php\nuse Guzzle\\Service\\Description\\ServiceDescription;\n\n$sd = new ServiceDescription();\n$sd->getOperations();           // @returns OperationInterface[]\n$sd->hasOperation($name);\n$sd->getOperation($name);       // @returns OperationInterface|null\n$sd->addOperation($operation);  // @param OperationInterface $operation\n```\n\n### Guzzle\\Common\\Inflection\\Inflector\n\nNamespace is now `Guzzle\\Inflection\\Inflector`\n\n### Guzzle\\Http\\Plugin\n\nNamespace is now `Guzzle\\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below.\n\n### Guzzle\\Http\\Plugin\\LogPlugin and Guzzle\\Common\\Log\n\nNow `Guzzle\\Plugin\\Log\\LogPlugin` and `Guzzle\\Log` respectively.\n\n**Before**\n\n```php\nuse Guzzle\\Common\\Log\\ClosureLogAdapter;\nuse Guzzle\\Http\\Plugin\\LogPlugin;\n\n/** @var \\Guzzle\\Http\\Client */\n$client;\n\n// $verbosity is an integer indicating desired message verbosity level\n$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE);\n```\n\n**After**\n\n```php\nuse Guzzle\\Log\\ClosureLogAdapter;\nuse Guzzle\\Log\\MessageFormatter;\nuse Guzzle\\Plugin\\Log\\LogPlugin;\n\n/** @var \\Guzzle\\Http\\Client */\n$client;\n\n// $format is a string indicating desired message format -- @see MessageFormatter\n$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT);\n```\n\n### Guzzle\\Http\\Plugin\\CurlAuthPlugin\n\nNow `Guzzle\\Plugin\\CurlAuth\\CurlAuthPlugin`.\n\n### Guzzle\\Http\\Plugin\\ExponentialBackoffPlugin\n\nNow `Guzzle\\Plugin\\Backoff\\BackoffPlugin`, and other changes.\n\n**Before**\n\n```php\nuse Guzzle\\Http\\Plugin\\ExponentialBackoffPlugin;\n\n$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge(\n        ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429)\n    ));\n\n$client->addSubscriber($backoffPlugin);\n```\n\n**After**\n\n```php\nuse Guzzle\\Plugin\\Backoff\\BackoffPlugin;\nuse Guzzle\\Plugin\\Backoff\\HttpBackoffStrategy;\n\n// Use convenient factory method instead -- see implementation for ideas of what\n// you can do with chaining backoff strategies\n$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge(\n        HttpBackoffStrategy::getDefaultFailureCodes(), array(429)\n    ));\n$client->addSubscriber($backoffPlugin);\n```\n\n### Known Issues\n\n#### [BUG] Accept-Encoding header behavior changed unintentionally.\n\n(See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e)\n\nIn version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to\nproperly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen.\nSee issue #217 for a workaround, or use a version containing the fix.\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/composer.json",
    "content": "{\n    \"name\": \"guzzlehttp/guzzle\",\n    \"description\": \"Guzzle is a PHP HTTP client library\",\n    \"keywords\": [\n        \"framework\",\n        \"http\",\n        \"rest\",\n        \"web service\",\n        \"curl\",\n        \"client\",\n        \"HTTP client\",\n        \"PSR-7\",\n        \"PSR-18\"\n    ],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Graham Campbell\",\n            \"email\": \"hello@gjcampbell.co.uk\",\n            \"homepage\": \"https://github.com/GrahamCampbell\"\n        },\n        {\n            \"name\": \"Michael Dowling\",\n            \"email\": \"mtdowling@gmail.com\",\n            \"homepage\": \"https://github.com/mtdowling\"\n        },\n        {\n            \"name\": \"Jeremy Lindblom\",\n            \"email\": \"jeremeamia@gmail.com\",\n            \"homepage\": \"https://github.com/jeremeamia\"\n        },\n        {\n            \"name\": \"George Mponos\",\n            \"email\": \"gmponos@gmail.com\",\n            \"homepage\": \"https://github.com/gmponos\"\n        },\n        {\n            \"name\": \"Tobias Nyholm\",\n            \"email\": \"tobias.nyholm@gmail.com\",\n            \"homepage\": \"https://github.com/Nyholm\"\n        },\n        {\n            \"name\": \"Márk Sági-Kazár\",\n            \"email\": \"mark.sagikazar@gmail.com\",\n            \"homepage\": \"https://github.com/sagikazarmark\"\n        },\n        {\n            \"name\": \"Tobias Schultze\",\n            \"email\": \"webmaster@tubo-world.de\",\n            \"homepage\": \"https://github.com/Tobion\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^7.2.5 || ^8.0\",\n        \"ext-json\": \"*\",\n        \"guzzlehttp/promises\": \"^1.5\",\n        \"guzzlehttp/psr7\": \"^1.8.3 || ^2.1\",\n        \"psr/http-client\": \"^1.0\",\n        \"symfony/deprecation-contracts\": \"^2.2 || ^3.0\"\n    },\n    \"provide\": {\n        \"psr/http-client-implementation\": \"1.0\"\n    },\n    \"require-dev\": {\n        \"ext-curl\": \"*\",\n        \"bamarni/composer-bin-plugin\": \"^1.4.1\",\n        \"php-http/client-integration-tests\": \"^3.0\",\n        \"phpunit/phpunit\": \"^8.5.5 || ^9.3.5\",\n        \"psr/log\": \"^1.1 || ^2.0 || ^3.0\"\n    },\n    \"suggest\": {\n        \"ext-curl\": \"Required for CURL handler support\",\n        \"ext-intl\": \"Required for Internationalized Domain Name (IDN) support\",\n        \"psr/log\": \"Required for using the Log middleware\"\n    },\n    \"config\": {\n        \"preferred-install\": \"dist\",\n        \"sort-packages\": true\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"7.4-dev\"\n        }\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"GuzzleHttp\\\\\": \"src/\"\n        },\n        \"files\": [\n            \"src/functions_include.php\"\n        ]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"GuzzleHttp\\\\Tests\\\\\": \"tests/\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/BodySummarizer.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse Psr\\Http\\Message\\MessageInterface;\n\nfinal class BodySummarizer implements BodySummarizerInterface\n{\n    /**\n     * @var int|null\n     */\n    private $truncateAt;\n\n    public function __construct(int $truncateAt = null)\n    {\n        $this->truncateAt = $truncateAt;\n    }\n\n    /**\n     * Returns a summarized message body.\n     */\n    public function summarize(MessageInterface $message): ?string\n    {\n        return $this->truncateAt === null\n            ? \\GuzzleHttp\\Psr7\\Message::bodySummary($message)\n            : \\GuzzleHttp\\Psr7\\Message::bodySummary($message, $this->truncateAt);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse Psr\\Http\\Message\\MessageInterface;\n\ninterface BodySummarizerInterface\n{\n    /**\n     * Returns a summarized message body.\n     */\n    public function summarize(MessageInterface $message): ?string;\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Client.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Cookie\\CookieJar;\nuse GuzzleHttp\\Exception\\GuzzleException;\nuse GuzzleHttp\\Exception\\InvalidArgumentException;\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * @final\n */\nclass Client implements ClientInterface, \\Psr\\Http\\Client\\ClientInterface\n{\n    use ClientTrait;\n\n    /**\n     * @var array Default request options\n     */\n    private $config;\n\n    /**\n     * Clients accept an array of constructor parameters.\n     *\n     * Here's an example of creating a client using a base_uri and an array of\n     * default request options to apply to each request:\n     *\n     *     $client = new Client([\n     *         'base_uri'        => 'http://www.foo.com/1.0/',\n     *         'timeout'         => 0,\n     *         'allow_redirects' => false,\n     *         'proxy'           => '192.168.16.1:10'\n     *     ]);\n     *\n     * Client configuration settings include the following options:\n     *\n     * - handler: (callable) Function that transfers HTTP requests over the\n     *   wire. The function is called with a Psr7\\Http\\Message\\RequestInterface\n     *   and array of transfer options, and must return a\n     *   GuzzleHttp\\Promise\\PromiseInterface that is fulfilled with a\n     *   Psr7\\Http\\Message\\ResponseInterface on success.\n     *   If no handler is provided, a default handler will be created\n     *   that enables all of the request options below by attaching all of the\n     *   default middleware to the handler.\n     * - base_uri: (string|UriInterface) Base URI of the client that is merged\n     *   into relative URIs. Can be a string or instance of UriInterface.\n     * - **: any request option\n     *\n     * @param array $config Client configuration settings.\n     *\n     * @see \\GuzzleHttp\\RequestOptions for a list of available request options.\n     */\n    public function __construct(array $config = [])\n    {\n        if (!isset($config['handler'])) {\n            $config['handler'] = HandlerStack::create();\n        } elseif (!\\is_callable($config['handler'])) {\n            throw new InvalidArgumentException('handler must be a callable');\n        }\n\n        // Convert the base_uri to a UriInterface\n        if (isset($config['base_uri'])) {\n            $config['base_uri'] = Psr7\\Utils::uriFor($config['base_uri']);\n        }\n\n        $this->configureDefaults($config);\n    }\n\n    /**\n     * @param string $method\n     * @param array  $args\n     *\n     * @return PromiseInterface|ResponseInterface\n     *\n     * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0.\n     */\n    public function __call($method, $args)\n    {\n        if (\\count($args) < 1) {\n            throw new InvalidArgumentException('Magic request methods require a URI and optional options array');\n        }\n\n        $uri = $args[0];\n        $opts = $args[1] ?? [];\n\n        return \\substr($method, -5) === 'Async'\n            ? $this->requestAsync(\\substr($method, 0, -5), $uri, $opts)\n            : $this->request($method, $uri, $opts);\n    }\n\n    /**\n     * Asynchronously send an HTTP request.\n     *\n     * @param array $options Request options to apply to the given\n     *                       request and to the transfer. See \\GuzzleHttp\\RequestOptions.\n     */\n    public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface\n    {\n        // Merge the base URI into the request URI if needed.\n        $options = $this->prepareDefaults($options);\n\n        return $this->transfer(\n            $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),\n            $options\n        );\n    }\n\n    /**\n     * Send an HTTP request.\n     *\n     * @param array $options Request options to apply to the given\n     *                       request and to the transfer. See \\GuzzleHttp\\RequestOptions.\n     *\n     * @throws GuzzleException\n     */\n    public function send(RequestInterface $request, array $options = []): ResponseInterface\n    {\n        $options[RequestOptions::SYNCHRONOUS] = true;\n        return $this->sendAsync($request, $options)->wait();\n    }\n\n    /**\n     * The HttpClient PSR (PSR-18) specify this method.\n     *\n     * @inheritDoc\n     */\n    public function sendRequest(RequestInterface $request): ResponseInterface\n    {\n        $options[RequestOptions::SYNCHRONOUS] = true;\n        $options[RequestOptions::ALLOW_REDIRECTS] = false;\n        $options[RequestOptions::HTTP_ERRORS] = false;\n\n        return $this->sendAsync($request, $options)->wait();\n    }\n\n    /**\n     * Create and send an asynchronous HTTP request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string              $method  HTTP method\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply. See \\GuzzleHttp\\RequestOptions.\n     */\n    public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface\n    {\n        $options = $this->prepareDefaults($options);\n        // Remove request modifying parameter because it can be done up-front.\n        $headers = $options['headers'] ?? [];\n        $body = $options['body'] ?? null;\n        $version = $options['version'] ?? '1.1';\n        // Merge the URI into the base URI.\n        $uri = $this->buildUri(Psr7\\Utils::uriFor($uri), $options);\n        if (\\is_array($body)) {\n            throw $this->invalidBody();\n        }\n        $request = new Psr7\\Request($method, $uri, $headers, $body, $version);\n        // Remove the option so that they are not doubly-applied.\n        unset($options['headers'], $options['body'], $options['version']);\n\n        return $this->transfer($request, $options);\n    }\n\n    /**\n     * Create and send an HTTP request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string              $method  HTTP method.\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply. See \\GuzzleHttp\\RequestOptions.\n     *\n     * @throws GuzzleException\n     */\n    public function request(string $method, $uri = '', array $options = []): ResponseInterface\n    {\n        $options[RequestOptions::SYNCHRONOUS] = true;\n        return $this->requestAsync($method, $uri, $options)->wait();\n    }\n\n    /**\n     * Get a client configuration option.\n     *\n     * These options include default request options of the client, a \"handler\"\n     * (if utilized by the concrete client), and a \"base_uri\" if utilized by\n     * the concrete client.\n     *\n     * @param string|null $option The config option to retrieve.\n     *\n     * @return mixed\n     *\n     * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.\n     */\n    public function getConfig(?string $option = null)\n    {\n        return $option === null\n            ? $this->config\n            : ($this->config[$option] ?? null);\n    }\n\n    private function buildUri(UriInterface $uri, array $config): UriInterface\n    {\n        if (isset($config['base_uri'])) {\n            $uri = Psr7\\UriResolver::resolve(Psr7\\Utils::uriFor($config['base_uri']), $uri);\n        }\n\n        if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {\n            $idnOptions = ($config['idn_conversion'] === true) ? \\IDNA_DEFAULT : $config['idn_conversion'];\n            $uri = Utils::idnUriConvert($uri, $idnOptions);\n        }\n\n        return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;\n    }\n\n    /**\n     * Configures the default options for a client.\n     */\n    private function configureDefaults(array $config): void\n    {\n        $defaults = [\n            'allow_redirects' => RedirectMiddleware::$defaultSettings,\n            'http_errors'     => true,\n            'decode_content'  => true,\n            'verify'          => true,\n            'cookies'         => false,\n            'idn_conversion'  => false,\n        ];\n\n        // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.\n\n        // We can only trust the HTTP_PROXY environment variable in a CLI\n        // process due to the fact that PHP has no reliable mechanism to\n        // get environment variables that start with \"HTTP_\".\n        if (\\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) {\n            $defaults['proxy']['http'] = $proxy;\n        }\n\n        if ($proxy = Utils::getenv('HTTPS_PROXY')) {\n            $defaults['proxy']['https'] = $proxy;\n        }\n\n        if ($noProxy = Utils::getenv('NO_PROXY')) {\n            $cleanedNoProxy = \\str_replace(' ', '', $noProxy);\n            $defaults['proxy']['no'] = \\explode(',', $cleanedNoProxy);\n        }\n\n        $this->config = $config + $defaults;\n\n        if (!empty($config['cookies']) && $config['cookies'] === true) {\n            $this->config['cookies'] = new CookieJar();\n        }\n\n        // Add the default user-agent header.\n        if (!isset($this->config['headers'])) {\n            $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()];\n        } else {\n            // Add the User-Agent header if one was not already set.\n            foreach (\\array_keys($this->config['headers']) as $name) {\n                if (\\strtolower($name) === 'user-agent') {\n                    return;\n                }\n            }\n            $this->config['headers']['User-Agent'] = Utils::defaultUserAgent();\n        }\n    }\n\n    /**\n     * Merges default options into the array.\n     *\n     * @param array $options Options to modify by reference\n     */\n    private function prepareDefaults(array $options): array\n    {\n        $defaults = $this->config;\n\n        if (!empty($defaults['headers'])) {\n            // Default headers are only added if they are not present.\n            $defaults['_conditional'] = $defaults['headers'];\n            unset($defaults['headers']);\n        }\n\n        // Special handling for headers is required as they are added as\n        // conditional headers and as headers passed to a request ctor.\n        if (\\array_key_exists('headers', $options)) {\n            // Allows default headers to be unset.\n            if ($options['headers'] === null) {\n                $defaults['_conditional'] = [];\n                unset($options['headers']);\n            } elseif (!\\is_array($options['headers'])) {\n                throw new InvalidArgumentException('headers must be an array');\n            }\n        }\n\n        // Shallow merge defaults underneath options.\n        $result = $options + $defaults;\n\n        // Remove null values.\n        foreach ($result as $k => $v) {\n            if ($v === null) {\n                unset($result[$k]);\n            }\n        }\n\n        return $result;\n    }\n\n    /**\n     * Transfers the given request and applies request options.\n     *\n     * The URI of the request is not modified and the request options are used\n     * as-is without merging in default options.\n     *\n     * @param array $options See \\GuzzleHttp\\RequestOptions.\n     */\n    private function transfer(RequestInterface $request, array $options): PromiseInterface\n    {\n        $request = $this->applyOptions($request, $options);\n        /** @var HandlerStack $handler */\n        $handler = $options['handler'];\n\n        try {\n            return P\\Create::promiseFor($handler($request, $options));\n        } catch (\\Exception $e) {\n            return P\\Create::rejectionFor($e);\n        }\n    }\n\n    /**\n     * Applies the array of request options to a request.\n     */\n    private function applyOptions(RequestInterface $request, array &$options): RequestInterface\n    {\n        $modify = [\n            'set_headers' => [],\n        ];\n\n        if (isset($options['headers'])) {\n            if (array_keys($options['headers']) === range(0, count($options['headers']) - 1)) {\n                throw new InvalidArgumentException('The headers array must have header name as keys.');\n            }\n            $modify['set_headers'] = $options['headers'];\n            unset($options['headers']);\n        }\n\n        if (isset($options['form_params'])) {\n            if (isset($options['multipart'])) {\n                throw new InvalidArgumentException('You cannot use '\n                    . 'form_params and multipart at the same time. Use the '\n                    . 'form_params option if you want to send application/'\n                    . 'x-www-form-urlencoded requests, and the multipart '\n                    . 'option to send multipart/form-data requests.');\n            }\n            $options['body'] = \\http_build_query($options['form_params'], '', '&');\n            unset($options['form_params']);\n            // Ensure that we don't have the header in different case and set the new value.\n            $options['_conditional'] = Psr7\\Utils::caselessRemove(['Content-Type'], $options['_conditional']);\n            $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';\n        }\n\n        if (isset($options['multipart'])) {\n            $options['body'] = new Psr7\\MultipartStream($options['multipart']);\n            unset($options['multipart']);\n        }\n\n        if (isset($options['json'])) {\n            $options['body'] = Utils::jsonEncode($options['json']);\n            unset($options['json']);\n            // Ensure that we don't have the header in different case and set the new value.\n            $options['_conditional'] = Psr7\\Utils::caselessRemove(['Content-Type'], $options['_conditional']);\n            $options['_conditional']['Content-Type'] = 'application/json';\n        }\n\n        if (!empty($options['decode_content'])\n            && $options['decode_content'] !== true\n        ) {\n            // Ensure that we don't have the header in different case and set the new value.\n            $options['_conditional'] = Psr7\\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']);\n            $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];\n        }\n\n        if (isset($options['body'])) {\n            if (\\is_array($options['body'])) {\n                throw $this->invalidBody();\n            }\n            $modify['body'] = Psr7\\Utils::streamFor($options['body']);\n            unset($options['body']);\n        }\n\n        if (!empty($options['auth']) && \\is_array($options['auth'])) {\n            $value = $options['auth'];\n            $type = isset($value[2]) ? \\strtolower($value[2]) : 'basic';\n            switch ($type) {\n                case 'basic':\n                    // Ensure that we don't have the header in different case and set the new value.\n                    $modify['set_headers'] = Psr7\\Utils::caselessRemove(['Authorization'], $modify['set_headers']);\n                    $modify['set_headers']['Authorization'] = 'Basic '\n                        . \\base64_encode(\"$value[0]:$value[1]\");\n                    break;\n                case 'digest':\n                    // @todo: Do not rely on curl\n                    $options['curl'][\\CURLOPT_HTTPAUTH] = \\CURLAUTH_DIGEST;\n                    $options['curl'][\\CURLOPT_USERPWD] = \"$value[0]:$value[1]\";\n                    break;\n                case 'ntlm':\n                    $options['curl'][\\CURLOPT_HTTPAUTH] = \\CURLAUTH_NTLM;\n                    $options['curl'][\\CURLOPT_USERPWD] = \"$value[0]:$value[1]\";\n                    break;\n            }\n        }\n\n        if (isset($options['query'])) {\n            $value = $options['query'];\n            if (\\is_array($value)) {\n                $value = \\http_build_query($value, '', '&', \\PHP_QUERY_RFC3986);\n            }\n            if (!\\is_string($value)) {\n                throw new InvalidArgumentException('query must be a string or array');\n            }\n            $modify['query'] = $value;\n            unset($options['query']);\n        }\n\n        // Ensure that sink is not an invalid value.\n        if (isset($options['sink'])) {\n            // TODO: Add more sink validation?\n            if (\\is_bool($options['sink'])) {\n                throw new InvalidArgumentException('sink must not be a boolean');\n            }\n        }\n\n        $request = Psr7\\Utils::modifyRequest($request, $modify);\n        if ($request->getBody() instanceof Psr7\\MultipartStream) {\n            // Use a multipart/form-data POST if a Content-Type is not set.\n            // Ensure that we don't have the header in different case and set the new value.\n            $options['_conditional'] = Psr7\\Utils::caselessRemove(['Content-Type'], $options['_conditional']);\n            $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='\n                . $request->getBody()->getBoundary();\n        }\n\n        // Merge in conditional headers if they are not present.\n        if (isset($options['_conditional'])) {\n            // Build up the changes so it's in a single clone of the message.\n            $modify = [];\n            foreach ($options['_conditional'] as $k => $v) {\n                if (!$request->hasHeader($k)) {\n                    $modify['set_headers'][$k] = $v;\n                }\n            }\n            $request = Psr7\\Utils::modifyRequest($request, $modify);\n            // Don't pass this internal value along to middleware/handlers.\n            unset($options['_conditional']);\n        }\n\n        return $request;\n    }\n\n    /**\n     * Return an InvalidArgumentException with pre-set message.\n     */\n    private function invalidBody(): InvalidArgumentException\n    {\n        return new InvalidArgumentException('Passing in the \"body\" request '\n            . 'option as an array to send a request is not supported. '\n            . 'Please use the \"form_params\" request option to send a '\n            . 'application/x-www-form-urlencoded request, or the \"multipart\" '\n            . 'request option to send a multipart/form-data request.');\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/ClientInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Exception\\GuzzleException;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Client interface for sending HTTP requests.\n */\ninterface ClientInterface\n{\n    /**\n     * The Guzzle major version.\n     */\n    public const MAJOR_VERSION = 7;\n\n    /**\n     * Send an HTTP request.\n     *\n     * @param RequestInterface $request Request to send\n     * @param array            $options Request options to apply to the given\n     *                                  request and to the transfer.\n     *\n     * @throws GuzzleException\n     */\n    public function send(RequestInterface $request, array $options = []): ResponseInterface;\n\n    /**\n     * Asynchronously send an HTTP request.\n     *\n     * @param RequestInterface $request Request to send\n     * @param array            $options Request options to apply to the given\n     *                                  request and to the transfer.\n     */\n    public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface;\n\n    /**\n     * Create and send an HTTP request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string              $method  HTTP method.\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function request(string $method, $uri, array $options = []): ResponseInterface;\n\n    /**\n     * Create and send an asynchronous HTTP request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string              $method  HTTP method\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function requestAsync(string $method, $uri, array $options = []): PromiseInterface;\n\n    /**\n     * Get a client configuration option.\n     *\n     * These options include default request options of the client, a \"handler\"\n     * (if utilized by the concrete client), and a \"base_uri\" if utilized by\n     * the concrete client.\n     *\n     * @param string|null $option The config option to retrieve.\n     *\n     * @return mixed\n     *\n     * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.\n     */\n    public function getConfig(?string $option = null);\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/ClientTrait.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Exception\\GuzzleException;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Client interface for sending HTTP requests.\n */\ntrait ClientTrait\n{\n    /**\n     * Create and send an HTTP request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string              $method  HTTP method.\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    abstract public function request(string $method, $uri, array $options = []): ResponseInterface;\n\n    /**\n     * Create and send an HTTP GET request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function get($uri, array $options = []): ResponseInterface\n    {\n        return $this->request('GET', $uri, $options);\n    }\n\n    /**\n     * Create and send an HTTP HEAD request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function head($uri, array $options = []): ResponseInterface\n    {\n        return $this->request('HEAD', $uri, $options);\n    }\n\n    /**\n     * Create and send an HTTP PUT request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function put($uri, array $options = []): ResponseInterface\n    {\n        return $this->request('PUT', $uri, $options);\n    }\n\n    /**\n     * Create and send an HTTP POST request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function post($uri, array $options = []): ResponseInterface\n    {\n        return $this->request('POST', $uri, $options);\n    }\n\n    /**\n     * Create and send an HTTP PATCH request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function patch($uri, array $options = []): ResponseInterface\n    {\n        return $this->request('PATCH', $uri, $options);\n    }\n\n    /**\n     * Create and send an HTTP DELETE request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     *\n     * @throws GuzzleException\n     */\n    public function delete($uri, array $options = []): ResponseInterface\n    {\n        return $this->request('DELETE', $uri, $options);\n    }\n\n    /**\n     * Create and send an asynchronous HTTP request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string              $method  HTTP method\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    abstract public function requestAsync(string $method, $uri, array $options = []): PromiseInterface;\n\n    /**\n     * Create and send an asynchronous HTTP GET request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function getAsync($uri, array $options = []): PromiseInterface\n    {\n        return $this->requestAsync('GET', $uri, $options);\n    }\n\n    /**\n     * Create and send an asynchronous HTTP HEAD request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function headAsync($uri, array $options = []): PromiseInterface\n    {\n        return $this->requestAsync('HEAD', $uri, $options);\n    }\n\n    /**\n     * Create and send an asynchronous HTTP PUT request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function putAsync($uri, array $options = []): PromiseInterface\n    {\n        return $this->requestAsync('PUT', $uri, $options);\n    }\n\n    /**\n     * Create and send an asynchronous HTTP POST request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function postAsync($uri, array $options = []): PromiseInterface\n    {\n        return $this->requestAsync('POST', $uri, $options);\n    }\n\n    /**\n     * Create and send an asynchronous HTTP PATCH request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function patchAsync($uri, array $options = []): PromiseInterface\n    {\n        return $this->requestAsync('PATCH', $uri, $options);\n    }\n\n    /**\n     * Create and send an asynchronous HTTP DELETE request.\n     *\n     * Use an absolute path to override the base path of the client, or a\n     * relative path to append to the base path of the client. The URL can\n     * contain the query string as well. Use an array to provide a URL\n     * template and additional variables to use in the URL template expansion.\n     *\n     * @param string|UriInterface $uri     URI object or string.\n     * @param array               $options Request options to apply.\n     */\n    public function deleteAsync($uri, array $options = []): PromiseInterface\n    {\n        return $this->requestAsync('DELETE', $uri, $options);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Cookie;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\n/**\n * Cookie jar that stores cookies as an array\n */\nclass CookieJar implements CookieJarInterface\n{\n    /**\n     * @var SetCookie[] Loaded cookie data\n     */\n    private $cookies = [];\n\n    /**\n     * @var bool\n     */\n    private $strictMode;\n\n    /**\n     * @param bool  $strictMode  Set to true to throw exceptions when invalid\n     *                           cookies are added to the cookie jar.\n     * @param array $cookieArray Array of SetCookie objects or a hash of\n     *                           arrays that can be used with the SetCookie\n     *                           constructor\n     */\n    public function __construct(bool $strictMode = false, array $cookieArray = [])\n    {\n        $this->strictMode = $strictMode;\n\n        foreach ($cookieArray as $cookie) {\n            if (!($cookie instanceof SetCookie)) {\n                $cookie = new SetCookie($cookie);\n            }\n            $this->setCookie($cookie);\n        }\n    }\n\n    /**\n     * Create a new Cookie jar from an associative array and domain.\n     *\n     * @param array  $cookies Cookies to create the jar from\n     * @param string $domain  Domain to set the cookies to\n     */\n    public static function fromArray(array $cookies, string $domain): self\n    {\n        $cookieJar = new self();\n        foreach ($cookies as $name => $value) {\n            $cookieJar->setCookie(new SetCookie([\n                'Domain'  => $domain,\n                'Name'    => $name,\n                'Value'   => $value,\n                'Discard' => true\n            ]));\n        }\n\n        return $cookieJar;\n    }\n\n    /**\n     * Evaluate if this cookie should be persisted to storage\n     * that survives between requests.\n     *\n     * @param SetCookie $cookie              Being evaluated.\n     * @param bool      $allowSessionCookies If we should persist session cookies\n     */\n    public static function shouldPersist(SetCookie $cookie, bool $allowSessionCookies = false): bool\n    {\n        if ($cookie->getExpires() || $allowSessionCookies) {\n            if (!$cookie->getDiscard()) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Finds and returns the cookie based on the name\n     *\n     * @param string $name cookie name to search for\n     *\n     * @return SetCookie|null cookie that was found or null if not found\n     */\n    public function getCookieByName(string $name): ?SetCookie\n    {\n        foreach ($this->cookies as $cookie) {\n            if ($cookie->getName() !== null && \\strcasecmp($cookie->getName(), $name) === 0) {\n                return $cookie;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function toArray(): array\n    {\n        return \\array_map(static function (SetCookie $cookie): array {\n            return $cookie->toArray();\n        }, $this->getIterator()->getArrayCopy());\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void\n    {\n        if (!$domain) {\n            $this->cookies = [];\n            return;\n        } elseif (!$path) {\n            $this->cookies = \\array_filter(\n                $this->cookies,\n                static function (SetCookie $cookie) use ($domain): bool {\n                    return !$cookie->matchesDomain($domain);\n                }\n            );\n        } elseif (!$name) {\n            $this->cookies = \\array_filter(\n                $this->cookies,\n                static function (SetCookie $cookie) use ($path, $domain): bool {\n                    return !($cookie->matchesPath($path) &&\n                        $cookie->matchesDomain($domain));\n                }\n            );\n        } else {\n            $this->cookies = \\array_filter(\n                $this->cookies,\n                static function (SetCookie $cookie) use ($path, $domain, $name) {\n                    return !($cookie->getName() == $name &&\n                        $cookie->matchesPath($path) &&\n                        $cookie->matchesDomain($domain));\n                }\n            );\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function clearSessionCookies(): void\n    {\n        $this->cookies = \\array_filter(\n            $this->cookies,\n            static function (SetCookie $cookie): bool {\n                return !$cookie->getDiscard() && $cookie->getExpires();\n            }\n        );\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function setCookie(SetCookie $cookie): bool\n    {\n        // If the name string is empty (but not 0), ignore the set-cookie\n        // string entirely.\n        $name = $cookie->getName();\n        if (!$name && $name !== '0') {\n            return false;\n        }\n\n        // Only allow cookies with set and valid domain, name, value\n        $result = $cookie->validate();\n        if ($result !== true) {\n            if ($this->strictMode) {\n                throw new \\RuntimeException('Invalid cookie: ' . $result);\n            }\n            $this->removeCookieIfEmpty($cookie);\n            return false;\n        }\n\n        // Resolve conflicts with previously set cookies\n        foreach ($this->cookies as $i => $c) {\n\n            // Two cookies are identical, when their path, and domain are\n            // identical.\n            if ($c->getPath() != $cookie->getPath() ||\n                $c->getDomain() != $cookie->getDomain() ||\n                $c->getName() != $cookie->getName()\n            ) {\n                continue;\n            }\n\n            // The previously set cookie is a discard cookie and this one is\n            // not so allow the new cookie to be set\n            if (!$cookie->getDiscard() && $c->getDiscard()) {\n                unset($this->cookies[$i]);\n                continue;\n            }\n\n            // If the new cookie's expiration is further into the future, then\n            // replace the old cookie\n            if ($cookie->getExpires() > $c->getExpires()) {\n                unset($this->cookies[$i]);\n                continue;\n            }\n\n            // If the value has changed, we better change it\n            if ($cookie->getValue() !== $c->getValue()) {\n                unset($this->cookies[$i]);\n                continue;\n            }\n\n            // The cookie exists, so no need to continue\n            return false;\n        }\n\n        $this->cookies[] = $cookie;\n\n        return true;\n    }\n\n    public function count(): int\n    {\n        return \\count($this->cookies);\n    }\n\n    /**\n     * @return \\ArrayIterator<int, SetCookie>\n     */\n    public function getIterator(): \\ArrayIterator\n    {\n        return new \\ArrayIterator(\\array_values($this->cookies));\n    }\n\n    public function extractCookies(RequestInterface $request, ResponseInterface $response): void\n    {\n        if ($cookieHeader = $response->getHeader('Set-Cookie')) {\n            foreach ($cookieHeader as $cookie) {\n                $sc = SetCookie::fromString($cookie);\n                if (!$sc->getDomain()) {\n                    $sc->setDomain($request->getUri()->getHost());\n                }\n                if (0 !== \\strpos($sc->getPath(), '/')) {\n                    $sc->setPath($this->getCookiePathFromRequest($request));\n                }\n                $this->setCookie($sc);\n            }\n        }\n    }\n\n    /**\n     * Computes cookie path following RFC 6265 section 5.1.4\n     *\n     * @link https://tools.ietf.org/html/rfc6265#section-5.1.4\n     */\n    private function getCookiePathFromRequest(RequestInterface $request): string\n    {\n        $uriPath = $request->getUri()->getPath();\n        if ('' === $uriPath) {\n            return '/';\n        }\n        if (0 !== \\strpos($uriPath, '/')) {\n            return '/';\n        }\n        if ('/' === $uriPath) {\n            return '/';\n        }\n        $lastSlashPos = \\strrpos($uriPath, '/');\n        if (0 === $lastSlashPos || false === $lastSlashPos) {\n            return '/';\n        }\n\n        return \\substr($uriPath, 0, $lastSlashPos);\n    }\n\n    public function withCookieHeader(RequestInterface $request): RequestInterface\n    {\n        $values = [];\n        $uri = $request->getUri();\n        $scheme = $uri->getScheme();\n        $host = $uri->getHost();\n        $path = $uri->getPath() ?: '/';\n\n        foreach ($this->cookies as $cookie) {\n            if ($cookie->matchesPath($path) &&\n                $cookie->matchesDomain($host) &&\n                !$cookie->isExpired() &&\n                (!$cookie->getSecure() || $scheme === 'https')\n            ) {\n                $values[] = $cookie->getName() . '='\n                    . $cookie->getValue();\n            }\n        }\n\n        return $values\n            ? $request->withHeader('Cookie', \\implode('; ', $values))\n            : $request;\n    }\n\n    /**\n     * If a cookie already exists and the server asks to set it again with a\n     * null value, the cookie must be deleted.\n     */\n    private function removeCookieIfEmpty(SetCookie $cookie): void\n    {\n        $cookieValue = $cookie->getValue();\n        if ($cookieValue === null || $cookieValue === '') {\n            $this->clear(\n                $cookie->getDomain(),\n                $cookie->getPath(),\n                $cookie->getName()\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Cookie;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\n/**\n * Stores HTTP cookies.\n *\n * It extracts cookies from HTTP requests, and returns them in HTTP responses.\n * CookieJarInterface instances automatically expire contained cookies when\n * necessary. Subclasses are also responsible for storing and retrieving\n * cookies from a file, database, etc.\n *\n * @link https://docs.python.org/2/library/cookielib.html Inspiration\n * @extends \\IteratorAggregate<SetCookie>\n */\ninterface CookieJarInterface extends \\Countable, \\IteratorAggregate\n{\n    /**\n     * Create a request with added cookie headers.\n     *\n     * If no matching cookies are found in the cookie jar, then no Cookie\n     * header is added to the request and the same request is returned.\n     *\n     * @param RequestInterface $request Request object to modify.\n     *\n     * @return RequestInterface returns the modified request.\n     */\n    public function withCookieHeader(RequestInterface $request): RequestInterface;\n\n    /**\n     * Extract cookies from an HTTP response and store them in the CookieJar.\n     *\n     * @param RequestInterface  $request  Request that was sent\n     * @param ResponseInterface $response Response that was received\n     */\n    public function extractCookies(RequestInterface $request, ResponseInterface $response): void;\n\n    /**\n     * Sets a cookie in the cookie jar.\n     *\n     * @param SetCookie $cookie Cookie to set.\n     *\n     * @return bool Returns true on success or false on failure\n     */\n    public function setCookie(SetCookie $cookie): bool;\n\n    /**\n     * Remove cookies currently held in the cookie jar.\n     *\n     * Invoking this method without arguments will empty the whole cookie jar.\n     * If given a $domain argument only cookies belonging to that domain will\n     * be removed. If given a $domain and $path argument, cookies belonging to\n     * the specified path within that domain are removed. If given all three\n     * arguments, then the cookie with the specified name, path and domain is\n     * removed.\n     *\n     * @param string|null $domain Clears cookies matching a domain\n     * @param string|null $path   Clears cookies matching a domain and path\n     * @param string|null $name   Clears cookies matching a domain, path, and name\n     */\n    public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void;\n\n    /**\n     * Discard all sessions cookies.\n     *\n     * Removes cookies that don't have an expire field or a have a discard\n     * field set to true. To be called when the user agent shuts down according\n     * to RFC 2965.\n     */\n    public function clearSessionCookies(): void;\n\n    /**\n     * Converts the cookie jar to an array.\n     */\n    public function toArray(): array;\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Cookie;\n\nuse GuzzleHttp\\Utils;\n\n/**\n * Persists non-session cookies using a JSON formatted file\n */\nclass FileCookieJar extends CookieJar\n{\n    /**\n     * @var string filename\n     */\n    private $filename;\n\n    /**\n     * @var bool Control whether to persist session cookies or not.\n     */\n    private $storeSessionCookies;\n\n    /**\n     * Create a new FileCookieJar object\n     *\n     * @param string $cookieFile          File to store the cookie data\n     * @param bool   $storeSessionCookies Set to true to store session cookies\n     *                                    in the cookie jar.\n     *\n     * @throws \\RuntimeException if the file cannot be found or created\n     */\n    public function __construct(string $cookieFile, bool $storeSessionCookies = false)\n    {\n        parent::__construct();\n        $this->filename = $cookieFile;\n        $this->storeSessionCookies = $storeSessionCookies;\n\n        if (\\file_exists($cookieFile)) {\n            $this->load($cookieFile);\n        }\n    }\n\n    /**\n     * Saves the file when shutting down\n     */\n    public function __destruct()\n    {\n        $this->save($this->filename);\n    }\n\n    /**\n     * Saves the cookies to a file.\n     *\n     * @param string $filename File to save\n     *\n     * @throws \\RuntimeException if the file cannot be found or created\n     */\n    public function save(string $filename): void\n    {\n        $json = [];\n        /** @var SetCookie $cookie */\n        foreach ($this as $cookie) {\n            if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {\n                $json[] = $cookie->toArray();\n            }\n        }\n\n        $jsonStr = Utils::jsonEncode($json);\n        if (false === \\file_put_contents($filename, $jsonStr, \\LOCK_EX)) {\n            throw new \\RuntimeException(\"Unable to save file {$filename}\");\n        }\n    }\n\n    /**\n     * Load cookies from a JSON formatted file.\n     *\n     * Old cookies are kept unless overwritten by newly loaded ones.\n     *\n     * @param string $filename Cookie file to load.\n     *\n     * @throws \\RuntimeException if the file cannot be loaded.\n     */\n    public function load(string $filename): void\n    {\n        $json = \\file_get_contents($filename);\n        if (false === $json) {\n            throw new \\RuntimeException(\"Unable to load file {$filename}\");\n        }\n        if ($json === '') {\n            return;\n        }\n\n        $data = Utils::jsonDecode($json, true);\n        if (\\is_array($data)) {\n            foreach ($data as $cookie) {\n                $this->setCookie(new SetCookie($cookie));\n            }\n        } elseif (\\is_scalar($data) && !empty($data)) {\n            throw new \\RuntimeException(\"Invalid cookie file: {$filename}\");\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Cookie;\n\n/**\n * Persists cookies in the client session\n */\nclass SessionCookieJar extends CookieJar\n{\n    /**\n     * @var string session key\n     */\n    private $sessionKey;\n\n    /**\n     * @var bool Control whether to persist session cookies or not.\n     */\n    private $storeSessionCookies;\n\n    /**\n     * Create a new SessionCookieJar object\n     *\n     * @param string $sessionKey          Session key name to store the cookie\n     *                                    data in session\n     * @param bool   $storeSessionCookies Set to true to store session cookies\n     *                                    in the cookie jar.\n     */\n    public function __construct(string $sessionKey, bool $storeSessionCookies = false)\n    {\n        parent::__construct();\n        $this->sessionKey = $sessionKey;\n        $this->storeSessionCookies = $storeSessionCookies;\n        $this->load();\n    }\n\n    /**\n     * Saves cookies to session when shutting down\n     */\n    public function __destruct()\n    {\n        $this->save();\n    }\n\n    /**\n     * Save cookies to the client session\n     */\n    public function save(): void\n    {\n        $json = [];\n        /** @var SetCookie $cookie */\n        foreach ($this as $cookie) {\n            if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {\n                $json[] = $cookie->toArray();\n            }\n        }\n\n        $_SESSION[$this->sessionKey] = \\json_encode($json);\n    }\n\n    /**\n     * Load the contents of the client session into the data array\n     */\n    protected function load(): void\n    {\n        if (!isset($_SESSION[$this->sessionKey])) {\n            return;\n        }\n        $data = \\json_decode($_SESSION[$this->sessionKey], true);\n        if (\\is_array($data)) {\n            foreach ($data as $cookie) {\n                $this->setCookie(new SetCookie($cookie));\n            }\n        } elseif (\\strlen($data)) {\n            throw new \\RuntimeException(\"Invalid cookie data\");\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Cookie;\n\n/**\n * Set-Cookie object\n */\nclass SetCookie\n{\n    /**\n     * @var array\n     */\n    private static $defaults = [\n        'Name'     => null,\n        'Value'    => null,\n        'Domain'   => null,\n        'Path'     => '/',\n        'Max-Age'  => null,\n        'Expires'  => null,\n        'Secure'   => false,\n        'Discard'  => false,\n        'HttpOnly' => false\n    ];\n\n    /**\n     * @var array Cookie data\n     */\n    private $data;\n\n    /**\n     * Create a new SetCookie object from a string.\n     *\n     * @param string $cookie Set-Cookie header string\n     */\n    public static function fromString(string $cookie): self\n    {\n        // Create the default return array\n        $data = self::$defaults;\n        // Explode the cookie string using a series of semicolons\n        $pieces = \\array_filter(\\array_map('trim', \\explode(';', $cookie)));\n        // The name of the cookie (first kvp) must exist and include an equal sign.\n        if (!isset($pieces[0]) || \\strpos($pieces[0], '=') === false) {\n            return new self($data);\n        }\n\n        // Add the cookie pieces into the parsed data array\n        foreach ($pieces as $part) {\n            $cookieParts = \\explode('=', $part, 2);\n            $key = \\trim($cookieParts[0]);\n            $value = isset($cookieParts[1])\n                ? \\trim($cookieParts[1], \" \\n\\r\\t\\0\\x0B\")\n                : true;\n\n            // Only check for non-cookies when cookies have been found\n            if (!isset($data['Name'])) {\n                $data['Name'] = $key;\n                $data['Value'] = $value;\n            } else {\n                foreach (\\array_keys(self::$defaults) as $search) {\n                    if (!\\strcasecmp($search, $key)) {\n                        $data[$search] = $value;\n                        continue 2;\n                    }\n                }\n                $data[$key] = $value;\n            }\n        }\n\n        return new self($data);\n    }\n\n    /**\n     * @param array $data Array of cookie data provided by a Cookie parser\n     */\n    public function __construct(array $data = [])\n    {\n        /** @var array|null $replaced will be null in case of replace error */\n        $replaced = \\array_replace(self::$defaults, $data);\n        if ($replaced === null) {\n            throw new \\InvalidArgumentException('Unable to replace the default values for the Cookie.');\n        }\n\n        $this->data = $replaced;\n        // Extract the Expires value and turn it into a UNIX timestamp if needed\n        if (!$this->getExpires() && $this->getMaxAge()) {\n            // Calculate the Expires date\n            $this->setExpires(\\time() + $this->getMaxAge());\n        } elseif (null !== ($expires = $this->getExpires()) && !\\is_numeric($expires)) {\n            $this->setExpires($expires);\n        }\n    }\n\n    public function __toString()\n    {\n        $str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; ';\n        foreach ($this->data as $k => $v) {\n            if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {\n                if ($k === 'Expires') {\n                    $str .= 'Expires=' . \\gmdate('D, d M Y H:i:s \\G\\M\\T', $v) . '; ';\n                } else {\n                    $str .= ($v === true ? $k : \"{$k}={$v}\") . '; ';\n                }\n            }\n        }\n\n        return \\rtrim($str, '; ');\n    }\n\n    public function toArray(): array\n    {\n        return $this->data;\n    }\n\n    /**\n     * Get the cookie name.\n     *\n     * @return string\n     */\n    public function getName()\n    {\n        return $this->data['Name'];\n    }\n\n    /**\n     * Set the cookie name.\n     *\n     * @param string $name Cookie name\n     */\n    public function setName($name): void\n    {\n        if (!is_string($name)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Name'] = (string) $name;\n    }\n\n    /**\n     * Get the cookie value.\n     *\n     * @return string|null\n     */\n    public function getValue()\n    {\n        return $this->data['Value'];\n    }\n\n    /**\n     * Set the cookie value.\n     *\n     * @param string $value Cookie value\n     */\n    public function setValue($value): void\n    {\n        if (!is_string($value)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Value'] = (string) $value;\n    }\n\n    /**\n     * Get the domain.\n     *\n     * @return string|null\n     */\n    public function getDomain()\n    {\n        return $this->data['Domain'];\n    }\n\n    /**\n     * Set the domain of the cookie.\n     *\n     * @param string|null $domain\n     */\n    public function setDomain($domain): void\n    {\n        if (!is_string($domain) && null !== $domain) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Domain'] = null === $domain ? null : (string) $domain;\n    }\n\n    /**\n     * Get the path.\n     *\n     * @return string\n     */\n    public function getPath()\n    {\n        return $this->data['Path'];\n    }\n\n    /**\n     * Set the path of the cookie.\n     *\n     * @param string $path Path of the cookie\n     */\n    public function setPath($path): void\n    {\n        if (!is_string($path)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Path'] = (string) $path;\n    }\n\n    /**\n     * Maximum lifetime of the cookie in seconds.\n     *\n     * @return int|null\n     */\n    public function getMaxAge()\n    {\n        return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age'];\n    }\n\n    /**\n     * Set the max-age of the cookie.\n     *\n     * @param int|null $maxAge Max age of the cookie in seconds\n     */\n    public function setMaxAge($maxAge): void\n    {\n        if (!is_int($maxAge) && null !== $maxAge) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge;\n    }\n\n    /**\n     * The UNIX timestamp when the cookie Expires.\n     *\n     * @return string|int|null\n     */\n    public function getExpires()\n    {\n        return $this->data['Expires'];\n    }\n\n    /**\n     * Set the unix timestamp for which the cookie will expire.\n     *\n     * @param int|string|null $timestamp Unix timestamp or any English textual datetime description.\n     */\n    public function setExpires($timestamp): void\n    {\n        if (!is_int($timestamp) && !is_string($timestamp) && null !== $timestamp) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Expires'] = null === $timestamp ? null : (\\is_numeric($timestamp) ? (int) $timestamp : \\strtotime((string) $timestamp));\n    }\n\n    /**\n     * Get whether or not this is a secure cookie.\n     *\n     * @return bool\n     */\n    public function getSecure()\n    {\n        return $this->data['Secure'];\n    }\n\n    /**\n     * Set whether or not the cookie is secure.\n     *\n     * @param bool $secure Set to true or false if secure\n     */\n    public function setSecure($secure): void\n    {\n        if (!is_bool($secure)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Secure'] = (bool) $secure;\n    }\n\n    /**\n     * Get whether or not this is a session cookie.\n     *\n     * @return bool|null\n     */\n    public function getDiscard()\n    {\n        return $this->data['Discard'];\n    }\n\n    /**\n     * Set whether or not this is a session cookie.\n     *\n     * @param bool $discard Set to true or false if this is a session cookie\n     */\n    public function setDiscard($discard): void\n    {\n        if (!is_bool($discard)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['Discard'] = (bool) $discard;\n    }\n\n    /**\n     * Get whether or not this is an HTTP only cookie.\n     *\n     * @return bool\n     */\n    public function getHttpOnly()\n    {\n        return $this->data['HttpOnly'];\n    }\n\n    /**\n     * Set whether or not this is an HTTP only cookie.\n     *\n     * @param bool $httpOnly Set to true or false if this is HTTP only\n     */\n    public function setHttpOnly($httpOnly): void\n    {\n        if (!is_bool($httpOnly)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->data['HttpOnly'] = (bool) $httpOnly;\n    }\n\n    /**\n     * Check if the cookie matches a path value.\n     *\n     * A request-path path-matches a given cookie-path if at least one of\n     * the following conditions holds:\n     *\n     * - The cookie-path and the request-path are identical.\n     * - The cookie-path is a prefix of the request-path, and the last\n     *   character of the cookie-path is %x2F (\"/\").\n     * - The cookie-path is a prefix of the request-path, and the first\n     *   character of the request-path that is not included in the cookie-\n     *   path is a %x2F (\"/\") character.\n     *\n     * @param string $requestPath Path to check against\n     */\n    public function matchesPath(string $requestPath): bool\n    {\n        $cookiePath = $this->getPath();\n\n        // Match on exact matches or when path is the default empty \"/\"\n        if ($cookiePath === '/' || $cookiePath == $requestPath) {\n            return true;\n        }\n\n        // Ensure that the cookie-path is a prefix of the request path.\n        if (0 !== \\strpos($requestPath, $cookiePath)) {\n            return false;\n        }\n\n        // Match if the last character of the cookie-path is \"/\"\n        if (\\substr($cookiePath, -1, 1) === '/') {\n            return true;\n        }\n\n        // Match if the first character not included in cookie path is \"/\"\n        return \\substr($requestPath, \\strlen($cookiePath), 1) === '/';\n    }\n\n    /**\n     * Check if the cookie matches a domain value.\n     *\n     * @param string $domain Domain to check against\n     */\n    public function matchesDomain(string $domain): bool\n    {\n        $cookieDomain = $this->getDomain();\n        if (null === $cookieDomain) {\n            return true;\n        }\n\n        // Remove the leading '.' as per spec in RFC 6265.\n        // https://tools.ietf.org/html/rfc6265#section-5.2.3\n        $cookieDomain = \\ltrim($cookieDomain, '.');\n\n        // Domain not set or exact match.\n        if (!$cookieDomain || !\\strcasecmp($domain, $cookieDomain)) {\n            return true;\n        }\n\n        // Matching the subdomain according to RFC 6265.\n        // https://tools.ietf.org/html/rfc6265#section-5.1.3\n        if (\\filter_var($domain, \\FILTER_VALIDATE_IP)) {\n            return false;\n        }\n\n        return (bool) \\preg_match('/\\.' . \\preg_quote($cookieDomain, '/') . '$/', $domain);\n    }\n\n    /**\n     * Check if the cookie is expired.\n     */\n    public function isExpired(): bool\n    {\n        return $this->getExpires() !== null && \\time() > $this->getExpires();\n    }\n\n    /**\n     * Check if the cookie is valid according to RFC 6265.\n     *\n     * @return bool|string Returns true if valid or an error message if invalid\n     */\n    public function validate()\n    {\n        $name = $this->getName();\n        if ($name === '') {\n            return 'The cookie name must not be empty';\n        }\n\n        // Check if any of the invalid characters are present in the cookie name\n        if (\\preg_match(\n            '/[\\x00-\\x20\\x22\\x28-\\x29\\x2c\\x2f\\x3a-\\x40\\x5c\\x7b\\x7d\\x7f]/',\n            $name\n        )) {\n            return 'Cookie name must not contain invalid characters: ASCII '\n                . 'Control characters (0-31;127), space, tab and the '\n                . 'following characters: ()<>@,;:\\\"/?={}';\n        }\n\n        // Value must not be null. 0 and empty string are valid. Empty strings\n        // are technically against RFC 6265, but known to happen in the wild.\n        $value = $this->getValue();\n        if ($value === null) {\n            return 'The cookie value must not be empty';\n        }\n\n        // Domains must not be empty, but can be 0. \"0\" is not a valid internet\n        // domain, but may be used as server name in a private network.\n        $domain = $this->getDomain();\n        if ($domain === null || $domain === '') {\n            return 'The cookie domain must not be empty';\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\n/**\n * Exception when an HTTP error occurs (4xx or 5xx error)\n */\nclass BadResponseException extends RequestException\n{\n    public function __construct(\n        string $message,\n        RequestInterface $request,\n        ResponseInterface $response,\n        \\Throwable $previous = null,\n        array $handlerContext = []\n    ) {\n        parent::__construct($message, $request, $response, $previous, $handlerContext);\n    }\n\n    /**\n     * Current exception and the ones that extend it will always have a response.\n     */\n    public function hasResponse(): bool\n    {\n        return true;\n    }\n\n    /**\n     * This function narrows the return type from the parent class and does not allow it to be nullable.\n     */\n    public function getResponse(): ResponseInterface\n    {\n        /** @var ResponseInterface */\n        return parent::getResponse();\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/ClientException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\n/**\n * Exception when a client error is encountered (4xx codes)\n */\nclass ClientException extends BadResponseException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nuse Psr\\Http\\Client\\NetworkExceptionInterface;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Exception thrown when a connection cannot be established.\n *\n * Note that no response is present for a ConnectException\n */\nclass ConnectException extends TransferException implements NetworkExceptionInterface\n{\n    /**\n     * @var RequestInterface\n     */\n    private $request;\n\n    /**\n     * @var array\n     */\n    private $handlerContext;\n\n    public function __construct(\n        string $message,\n        RequestInterface $request,\n        \\Throwable $previous = null,\n        array $handlerContext = []\n    ) {\n        parent::__construct($message, 0, $previous);\n        $this->request = $request;\n        $this->handlerContext = $handlerContext;\n    }\n\n    /**\n     * Get the request that caused the exception\n     */\n    public function getRequest(): RequestInterface\n    {\n        return $this->request;\n    }\n\n    /**\n     * Get contextual information about the error from the underlying handler.\n     *\n     * The contents of this array will vary depending on which handler you are\n     * using. It may also be just an empty array. Relying on this data will\n     * couple you to a specific handler, but can give more debug information\n     * when needed.\n     */\n    public function getHandlerContext(): array\n    {\n        return $this->handlerContext;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nuse Psr\\Http\\Client\\ClientExceptionInterface;\n\ninterface GuzzleException extends ClientExceptionInterface\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nfinal class InvalidArgumentException extends \\InvalidArgumentException implements GuzzleException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/RequestException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nuse GuzzleHttp\\BodySummarizer;\nuse GuzzleHttp\\BodySummarizerInterface;\nuse Psr\\Http\\Client\\RequestExceptionInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * HTTP Request exception\n */\nclass RequestException extends TransferException implements RequestExceptionInterface\n{\n    /**\n     * @var RequestInterface\n     */\n    private $request;\n\n    /**\n     * @var ResponseInterface|null\n     */\n    private $response;\n\n    /**\n     * @var array\n     */\n    private $handlerContext;\n\n    public function __construct(\n        string $message,\n        RequestInterface $request,\n        ResponseInterface $response = null,\n        \\Throwable $previous = null,\n        array $handlerContext = []\n    ) {\n        // Set the code of the exception if the response is set and not future.\n        $code = $response ? $response->getStatusCode() : 0;\n        parent::__construct($message, $code, $previous);\n        $this->request = $request;\n        $this->response = $response;\n        $this->handlerContext = $handlerContext;\n    }\n\n    /**\n     * Wrap non-RequestExceptions with a RequestException\n     */\n    public static function wrapException(RequestInterface $request, \\Throwable $e): RequestException\n    {\n        return $e instanceof RequestException ? $e : new RequestException($e->getMessage(), $request, null, $e);\n    }\n\n    /**\n     * Factory method to create a new exception with a normalized error message\n     *\n     * @param RequestInterface             $request        Request sent\n     * @param ResponseInterface            $response       Response received\n     * @param \\Throwable|null              $previous       Previous exception\n     * @param array                        $handlerContext Optional handler context\n     * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer\n     */\n    public static function create(\n        RequestInterface $request,\n        ResponseInterface $response = null,\n        \\Throwable $previous = null,\n        array $handlerContext = [],\n        BodySummarizerInterface $bodySummarizer = null\n    ): self {\n        if (!$response) {\n            return new self(\n                'Error completing request',\n                $request,\n                null,\n                $previous,\n                $handlerContext\n            );\n        }\n\n        $level = (int) \\floor($response->getStatusCode() / 100);\n        if ($level === 4) {\n            $label = 'Client error';\n            $className = ClientException::class;\n        } elseif ($level === 5) {\n            $label = 'Server error';\n            $className = ServerException::class;\n        } else {\n            $label = 'Unsuccessful request';\n            $className = __CLASS__;\n        }\n\n        $uri = $request->getUri();\n        $uri = static::obfuscateUri($uri);\n\n        // Client Error: `GET /` resulted in a `404 Not Found` response:\n        // <html> ... (truncated)\n        $message = \\sprintf(\n            '%s: `%s %s` resulted in a `%s %s` response',\n            $label,\n            $request->getMethod(),\n            $uri->__toString(),\n            $response->getStatusCode(),\n            $response->getReasonPhrase()\n        );\n\n        $summary = ($bodySummarizer ?? new BodySummarizer())->summarize($response);\n\n        if ($summary !== null) {\n            $message .= \":\\n{$summary}\\n\";\n        }\n\n        return new $className($message, $request, $response, $previous, $handlerContext);\n    }\n\n    /**\n     * Obfuscates URI if there is a username and a password present\n     */\n    private static function obfuscateUri(UriInterface $uri): UriInterface\n    {\n        $userInfo = $uri->getUserInfo();\n\n        if (false !== ($pos = \\strpos($userInfo, ':'))) {\n            return $uri->withUserInfo(\\substr($userInfo, 0, $pos), '***');\n        }\n\n        return $uri;\n    }\n\n    /**\n     * Get the request that caused the exception\n     */\n    public function getRequest(): RequestInterface\n    {\n        return $this->request;\n    }\n\n    /**\n     * Get the associated response\n     */\n    public function getResponse(): ?ResponseInterface\n    {\n        return $this->response;\n    }\n\n    /**\n     * Check if a response was received\n     */\n    public function hasResponse(): bool\n    {\n        return $this->response !== null;\n    }\n\n    /**\n     * Get contextual information about the error from the underlying handler.\n     *\n     * The contents of this array will vary depending on which handler you are\n     * using. It may also be just an empty array. Relying on this data will\n     * couple you to a specific handler, but can give more debug information\n     * when needed.\n     */\n    public function getHandlerContext(): array\n    {\n        return $this->handlerContext;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/ServerException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\n/**\n * Exception when a server error is encountered (5xx codes)\n */\nclass ServerException extends BadResponseException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nclass TooManyRedirectsException extends RequestException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Exception/TransferException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Exception;\n\nclass TransferException extends \\RuntimeException implements GuzzleException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\FulfilledPromise;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse GuzzleHttp\\Psr7\\LazyOpenStream;\nuse GuzzleHttp\\TransferStats;\nuse GuzzleHttp\\Utils;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Creates curl resources from a request\n *\n * @final\n */\nclass CurlFactory implements CurlFactoryInterface\n{\n    public const CURL_VERSION_STR = 'curl_version';\n\n    /**\n     * @deprecated\n     */\n    public const LOW_CURL_VERSION_NUMBER = '7.21.2';\n\n    /**\n     * @var resource[]|\\CurlHandle[]\n     */\n    private $handles = [];\n\n    /**\n     * @var int Total number of idle handles to keep in cache\n     */\n    private $maxHandles;\n\n    /**\n     * @param int $maxHandles Maximum number of idle handles.\n     */\n    public function __construct(int $maxHandles)\n    {\n        $this->maxHandles = $maxHandles;\n    }\n\n    public function create(RequestInterface $request, array $options): EasyHandle\n    {\n        if (isset($options['curl']['body_as_string'])) {\n            $options['_body_as_string'] = $options['curl']['body_as_string'];\n            unset($options['curl']['body_as_string']);\n        }\n\n        $easy = new EasyHandle;\n        $easy->request = $request;\n        $easy->options = $options;\n        $conf = $this->getDefaultConf($easy);\n        $this->applyMethod($easy, $conf);\n        $this->applyHandlerOptions($easy, $conf);\n        $this->applyHeaders($easy, $conf);\n        unset($conf['_headers']);\n\n        // Add handler options from the request configuration options\n        if (isset($options['curl'])) {\n            $conf = \\array_replace($conf, $options['curl']);\n        }\n\n        $conf[\\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);\n        $easy->handle = $this->handles ? \\array_pop($this->handles) : \\curl_init();\n        curl_setopt_array($easy->handle, $conf);\n\n        return $easy;\n    }\n\n    public function release(EasyHandle $easy): void\n    {\n        $resource = $easy->handle;\n        unset($easy->handle);\n\n        if (\\count($this->handles) >= $this->maxHandles) {\n            \\curl_close($resource);\n        } else {\n            // Remove all callback functions as they can hold onto references\n            // and are not cleaned up by curl_reset. Using curl_setopt_array\n            // does not work for some reason, so removing each one\n            // individually.\n            \\curl_setopt($resource, \\CURLOPT_HEADERFUNCTION, null);\n            \\curl_setopt($resource, \\CURLOPT_READFUNCTION, null);\n            \\curl_setopt($resource, \\CURLOPT_WRITEFUNCTION, null);\n            \\curl_setopt($resource, \\CURLOPT_PROGRESSFUNCTION, null);\n            \\curl_reset($resource);\n            $this->handles[] = $resource;\n        }\n    }\n\n    /**\n     * Completes a cURL transaction, either returning a response promise or a\n     * rejected promise.\n     *\n     * @param callable(RequestInterface, array): PromiseInterface $handler\n     * @param CurlFactoryInterface                                $factory Dictates how the handle is released\n     */\n    public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface\n    {\n        if (isset($easy->options['on_stats'])) {\n            self::invokeStats($easy);\n        }\n\n        if (!$easy->response || $easy->errno) {\n            return self::finishError($handler, $easy, $factory);\n        }\n\n        // Return the response if it is present and there is no error.\n        $factory->release($easy);\n\n        // Rewind the body of the response if possible.\n        $body = $easy->response->getBody();\n        if ($body->isSeekable()) {\n            $body->rewind();\n        }\n\n        return new FulfilledPromise($easy->response);\n    }\n\n    private static function invokeStats(EasyHandle $easy): void\n    {\n        $curlStats = \\curl_getinfo($easy->handle);\n        $curlStats['appconnect_time'] = \\curl_getinfo($easy->handle, \\CURLINFO_APPCONNECT_TIME);\n        $stats = new TransferStats(\n            $easy->request,\n            $easy->response,\n            $curlStats['total_time'],\n            $easy->errno,\n            $curlStats\n        );\n        ($easy->options['on_stats'])($stats);\n    }\n\n    /**\n     * @param callable(RequestInterface, array): PromiseInterface $handler\n     */\n    private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface\n    {\n        // Get error information and release the handle to the factory.\n        $ctx = [\n            'errno' => $easy->errno,\n            'error' => \\curl_error($easy->handle),\n            'appconnect_time' => \\curl_getinfo($easy->handle, \\CURLINFO_APPCONNECT_TIME),\n        ] + \\curl_getinfo($easy->handle);\n        $ctx[self::CURL_VERSION_STR] = \\curl_version()['version'];\n        $factory->release($easy);\n\n        // Retry when nothing is present or when curl failed to rewind.\n        if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) {\n            return self::retryFailedRewind($handler, $easy, $ctx);\n        }\n\n        return self::createRejection($easy, $ctx);\n    }\n\n    private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface\n    {\n        static $connectionErrors = [\n            \\CURLE_OPERATION_TIMEOUTED  => true,\n            \\CURLE_COULDNT_RESOLVE_HOST => true,\n            \\CURLE_COULDNT_CONNECT      => true,\n            \\CURLE_SSL_CONNECT_ERROR    => true,\n            \\CURLE_GOT_NOTHING          => true,\n        ];\n\n        if ($easy->createResponseException) {\n            return P\\Create::rejectionFor(\n                new RequestException(\n                    'An error was encountered while creating the response',\n                    $easy->request,\n                    $easy->response,\n                    $easy->createResponseException,\n                    $ctx\n                )\n            );\n        }\n\n        // If an exception was encountered during the onHeaders event, then\n        // return a rejected promise that wraps that exception.\n        if ($easy->onHeadersException) {\n            return P\\Create::rejectionFor(\n                new RequestException(\n                    'An error was encountered during the on_headers event',\n                    $easy->request,\n                    $easy->response,\n                    $easy->onHeadersException,\n                    $ctx\n                )\n            );\n        }\n\n        $message = \\sprintf(\n            'cURL error %s: %s (%s)',\n            $ctx['errno'],\n            $ctx['error'],\n            'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'\n        );\n        $uriString = (string) $easy->request->getUri();\n        if ($uriString !== '' && false === \\strpos($ctx['error'], $uriString)) {\n            $message .= \\sprintf(' for %s', $uriString);\n        }\n\n        // Create a connection exception if it was a specific error code.\n        $error = isset($connectionErrors[$easy->errno])\n            ? new ConnectException($message, $easy->request, null, $ctx)\n            : new RequestException($message, $easy->request, $easy->response, null, $ctx);\n\n        return P\\Create::rejectionFor($error);\n    }\n\n    /**\n     * @return array<int|string, mixed>\n     */\n    private function getDefaultConf(EasyHandle $easy): array\n    {\n        $conf = [\n            '_headers'              => $easy->request->getHeaders(),\n            \\CURLOPT_CUSTOMREQUEST  => $easy->request->getMethod(),\n            \\CURLOPT_URL            => (string) $easy->request->getUri()->withFragment(''),\n            \\CURLOPT_RETURNTRANSFER => false,\n            \\CURLOPT_HEADER         => false,\n            \\CURLOPT_CONNECTTIMEOUT => 150,\n        ];\n\n        if (\\defined('CURLOPT_PROTOCOLS')) {\n            $conf[\\CURLOPT_PROTOCOLS] = \\CURLPROTO_HTTP | \\CURLPROTO_HTTPS;\n        }\n\n        $version = $easy->request->getProtocolVersion();\n        if ($version == 1.1) {\n            $conf[\\CURLOPT_HTTP_VERSION] = \\CURL_HTTP_VERSION_1_1;\n        } elseif ($version == 2.0) {\n            $conf[\\CURLOPT_HTTP_VERSION] = \\CURL_HTTP_VERSION_2_0;\n        } else {\n            $conf[\\CURLOPT_HTTP_VERSION] = \\CURL_HTTP_VERSION_1_0;\n        }\n\n        return $conf;\n    }\n\n    private function applyMethod(EasyHandle $easy, array &$conf): void\n    {\n        $body = $easy->request->getBody();\n        $size = $body->getSize();\n\n        if ($size === null || $size > 0) {\n            $this->applyBody($easy->request, $easy->options, $conf);\n            return;\n        }\n\n        $method = $easy->request->getMethod();\n        if ($method === 'PUT' || $method === 'POST') {\n            // See https://tools.ietf.org/html/rfc7230#section-3.3.2\n            if (!$easy->request->hasHeader('Content-Length')) {\n                $conf[\\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';\n            }\n        } elseif ($method === 'HEAD') {\n            $conf[\\CURLOPT_NOBODY] = true;\n            unset(\n                $conf[\\CURLOPT_WRITEFUNCTION],\n                $conf[\\CURLOPT_READFUNCTION],\n                $conf[\\CURLOPT_FILE],\n                $conf[\\CURLOPT_INFILE]\n            );\n        }\n    }\n\n    private function applyBody(RequestInterface $request, array $options, array &$conf): void\n    {\n        $size = $request->hasHeader('Content-Length')\n            ? (int) $request->getHeaderLine('Content-Length')\n            : null;\n\n        // Send the body as a string if the size is less than 1MB OR if the\n        // [curl][body_as_string] request value is set.\n        if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) {\n            $conf[\\CURLOPT_POSTFIELDS] = (string) $request->getBody();\n            // Don't duplicate the Content-Length header\n            $this->removeHeader('Content-Length', $conf);\n            $this->removeHeader('Transfer-Encoding', $conf);\n        } else {\n            $conf[\\CURLOPT_UPLOAD] = true;\n            if ($size !== null) {\n                $conf[\\CURLOPT_INFILESIZE] = $size;\n                $this->removeHeader('Content-Length', $conf);\n            }\n            $body = $request->getBody();\n            if ($body->isSeekable()) {\n                $body->rewind();\n            }\n            $conf[\\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) {\n                return $body->read($length);\n            };\n        }\n\n        // If the Expect header is not present, prevent curl from adding it\n        if (!$request->hasHeader('Expect')) {\n            $conf[\\CURLOPT_HTTPHEADER][] = 'Expect:';\n        }\n\n        // cURL sometimes adds a content-type by default. Prevent this.\n        if (!$request->hasHeader('Content-Type')) {\n            $conf[\\CURLOPT_HTTPHEADER][] = 'Content-Type:';\n        }\n    }\n\n    private function applyHeaders(EasyHandle $easy, array &$conf): void\n    {\n        foreach ($conf['_headers'] as $name => $values) {\n            foreach ($values as $value) {\n                $value = (string) $value;\n                if ($value === '') {\n                    // cURL requires a special format for empty headers.\n                    // See https://github.com/guzzle/guzzle/issues/1882 for more details.\n                    $conf[\\CURLOPT_HTTPHEADER][] = \"$name;\";\n                } else {\n                    $conf[\\CURLOPT_HTTPHEADER][] = \"$name: $value\";\n                }\n            }\n        }\n\n        // Remove the Accept header if one was not set\n        if (!$easy->request->hasHeader('Accept')) {\n            $conf[\\CURLOPT_HTTPHEADER][] = 'Accept:';\n        }\n    }\n\n    /**\n     * Remove a header from the options array.\n     *\n     * @param string $name    Case-insensitive header to remove\n     * @param array  $options Array of options to modify\n     */\n    private function removeHeader(string $name, array &$options): void\n    {\n        foreach (\\array_keys($options['_headers']) as $key) {\n            if (!\\strcasecmp($key, $name)) {\n                unset($options['_headers'][$key]);\n                return;\n            }\n        }\n    }\n\n    private function applyHandlerOptions(EasyHandle $easy, array &$conf): void\n    {\n        $options = $easy->options;\n        if (isset($options['verify'])) {\n            if ($options['verify'] === false) {\n                unset($conf[\\CURLOPT_CAINFO]);\n                $conf[\\CURLOPT_SSL_VERIFYHOST] = 0;\n                $conf[\\CURLOPT_SSL_VERIFYPEER] = false;\n            } else {\n                $conf[\\CURLOPT_SSL_VERIFYHOST] = 2;\n                $conf[\\CURLOPT_SSL_VERIFYPEER] = true;\n                if (\\is_string($options['verify'])) {\n                    // Throw an error if the file/folder/link path is not valid or doesn't exist.\n                    if (!\\file_exists($options['verify'])) {\n                        throw new \\InvalidArgumentException(\"SSL CA bundle not found: {$options['verify']}\");\n                    }\n                    // If it's a directory or a link to a directory use CURLOPT_CAPATH.\n                    // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.\n                    if (\n                        \\is_dir($options['verify']) ||\n                        (\n                            \\is_link($options['verify']) === true &&\n                            ($verifyLink = \\readlink($options['verify'])) !== false &&\n                            \\is_dir($verifyLink)\n                        )\n                    ) {\n                        $conf[\\CURLOPT_CAPATH] = $options['verify'];\n                    } else {\n                        $conf[\\CURLOPT_CAINFO] = $options['verify'];\n                    }\n                }\n            }\n        }\n\n        if (!isset($options['curl'][\\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {\n            $accept = $easy->request->getHeaderLine('Accept-Encoding');\n            if ($accept) {\n                $conf[\\CURLOPT_ENCODING] = $accept;\n            } else {\n                // The empty string enables all available decoders and implicitly\n                // sets a matching 'Accept-Encoding' header.\n                $conf[\\CURLOPT_ENCODING] = '';\n                // But as the user did not specify any acceptable encodings we need\n                // to overwrite this implicit header with an empty one.\n                $conf[\\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';\n            }\n        }\n\n        if (!isset($options['sink'])) {\n            // Use a default temp stream if no sink was set.\n            $options['sink'] = \\GuzzleHttp\\Psr7\\Utils::tryFopen('php://temp', 'w+');\n        }\n        $sink = $options['sink'];\n        if (!\\is_string($sink)) {\n            $sink = \\GuzzleHttp\\Psr7\\Utils::streamFor($sink);\n        } elseif (!\\is_dir(\\dirname($sink))) {\n            // Ensure that the directory exists before failing in curl.\n            throw new \\RuntimeException(\\sprintf('Directory %s does not exist for sink value of %s', \\dirname($sink), $sink));\n        } else {\n            $sink = new LazyOpenStream($sink, 'w+');\n        }\n        $easy->sink = $sink;\n        $conf[\\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int {\n            return $sink->write($write);\n        };\n\n        $timeoutRequiresNoSignal = false;\n        if (isset($options['timeout'])) {\n            $timeoutRequiresNoSignal |= $options['timeout'] < 1;\n            $conf[\\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;\n        }\n\n        // CURL default value is CURL_IPRESOLVE_WHATEVER\n        if (isset($options['force_ip_resolve'])) {\n            if ('v4' === $options['force_ip_resolve']) {\n                $conf[\\CURLOPT_IPRESOLVE] = \\CURL_IPRESOLVE_V4;\n            } elseif ('v6' === $options['force_ip_resolve']) {\n                $conf[\\CURLOPT_IPRESOLVE] = \\CURL_IPRESOLVE_V6;\n            }\n        }\n\n        if (isset($options['connect_timeout'])) {\n            $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;\n            $conf[\\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;\n        }\n\n        if ($timeoutRequiresNoSignal && \\strtoupper(\\substr(\\PHP_OS, 0, 3)) !== 'WIN') {\n            $conf[\\CURLOPT_NOSIGNAL] = true;\n        }\n\n        if (isset($options['proxy'])) {\n            if (!\\is_array($options['proxy'])) {\n                $conf[\\CURLOPT_PROXY] = $options['proxy'];\n            } else {\n                $scheme = $easy->request->getUri()->getScheme();\n                if (isset($options['proxy'][$scheme])) {\n                    $host = $easy->request->getUri()->getHost();\n                    if (!isset($options['proxy']['no']) || !Utils::isHostInNoProxy($host, $options['proxy']['no'])) {\n                        $conf[\\CURLOPT_PROXY] = $options['proxy'][$scheme];\n                    }\n                }\n            }\n        }\n\n        if (isset($options['cert'])) {\n            $cert = $options['cert'];\n            if (\\is_array($cert)) {\n                $conf[\\CURLOPT_SSLCERTPASSWD] = $cert[1];\n                $cert = $cert[0];\n            }\n            if (!\\file_exists($cert)) {\n                throw new \\InvalidArgumentException(\"SSL certificate not found: {$cert}\");\n            }\n            # OpenSSL (versions 0.9.3 and later) also support \"P12\" for PKCS#12-encoded files.\n            # see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html\n            $ext = pathinfo($cert, \\PATHINFO_EXTENSION);\n            if (preg_match('#^(der|p12)$#i', $ext)) {\n                $conf[\\CURLOPT_SSLCERTTYPE] = strtoupper($ext);\n            }\n            $conf[\\CURLOPT_SSLCERT] = $cert;\n        }\n\n        if (isset($options['ssl_key'])) {\n            if (\\is_array($options['ssl_key'])) {\n                if (\\count($options['ssl_key']) === 2) {\n                    [$sslKey, $conf[\\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];\n                } else {\n                    [$sslKey] = $options['ssl_key'];\n                }\n            }\n\n            $sslKey = $sslKey ?? $options['ssl_key'];\n\n            if (!\\file_exists($sslKey)) {\n                throw new \\InvalidArgumentException(\"SSL private key not found: {$sslKey}\");\n            }\n            $conf[\\CURLOPT_SSLKEY] = $sslKey;\n        }\n\n        if (isset($options['progress'])) {\n            $progress = $options['progress'];\n            if (!\\is_callable($progress)) {\n                throw new \\InvalidArgumentException('progress client option must be callable');\n            }\n            $conf[\\CURLOPT_NOPROGRESS] = false;\n            $conf[\\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) {\n                $progress($downloadSize, $downloaded, $uploadSize, $uploaded);\n            };\n        }\n\n        if (!empty($options['debug'])) {\n            $conf[\\CURLOPT_STDERR] = Utils::debugResource($options['debug']);\n            $conf[\\CURLOPT_VERBOSE] = true;\n        }\n    }\n\n    /**\n     * This function ensures that a response was set on a transaction. If one\n     * was not set, then the request is retried if possible. This error\n     * typically means you are sending a payload, curl encountered a\n     * \"Connection died, retrying a fresh connect\" error, tried to rewind the\n     * stream, and then encountered a \"necessary data rewind wasn't possible\"\n     * error, causing the request to be sent through curl_multi_info_read()\n     * without an error status.\n     *\n     * @param callable(RequestInterface, array): PromiseInterface $handler\n     */\n    private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface\n    {\n        try {\n            // Only rewind if the body has been read from.\n            $body = $easy->request->getBody();\n            if ($body->tell() > 0) {\n                $body->rewind();\n            }\n        } catch (\\RuntimeException $e) {\n            $ctx['error'] = 'The connection unexpectedly failed without '\n                . 'providing an error. The request would have been retried, '\n                . 'but attempting to rewind the request body failed. '\n                . 'Exception: ' . $e;\n            return self::createRejection($easy, $ctx);\n        }\n\n        // Retry no more than 3 times before giving up.\n        if (!isset($easy->options['_curl_retries'])) {\n            $easy->options['_curl_retries'] = 1;\n        } elseif ($easy->options['_curl_retries'] == 2) {\n            $ctx['error'] = 'The cURL request was retried 3 times '\n                . 'and did not succeed. The most likely reason for the failure '\n                . 'is that cURL was unable to rewind the body of the request '\n                . 'and subsequent retries resulted in the same error. Turn on '\n                . 'the debug option to see what went wrong. See '\n                . 'https://bugs.php.net/bug.php?id=47204 for more information.';\n            return self::createRejection($easy, $ctx);\n        } else {\n            $easy->options['_curl_retries']++;\n        }\n\n        return $handler($easy->request, $easy->options);\n    }\n\n    private function createHeaderFn(EasyHandle $easy): callable\n    {\n        if (isset($easy->options['on_headers'])) {\n            $onHeaders = $easy->options['on_headers'];\n\n            if (!\\is_callable($onHeaders)) {\n                throw new \\InvalidArgumentException('on_headers must be callable');\n            }\n        } else {\n            $onHeaders = null;\n        }\n\n        return static function ($ch, $h) use (\n            $onHeaders,\n            $easy,\n            &$startingResponse\n        ) {\n            $value = \\trim($h);\n            if ($value === '') {\n                $startingResponse = true;\n                try {\n                    $easy->createResponse();\n                } catch (\\Exception $e) {\n                    $easy->createResponseException = $e;\n                    return -1;\n                }\n                if ($onHeaders !== null) {\n                    try {\n                        $onHeaders($easy->response);\n                    } catch (\\Exception $e) {\n                        // Associate the exception with the handle and trigger\n                        // a curl header write error by returning 0.\n                        $easy->onHeadersException = $e;\n                        return -1;\n                    }\n                }\n            } elseif ($startingResponse) {\n                $startingResponse = false;\n                $easy->headers = [$value];\n            } else {\n                $easy->headers[] = $value;\n            }\n            return \\strlen($h);\n        };\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse Psr\\Http\\Message\\RequestInterface;\n\ninterface CurlFactoryInterface\n{\n    /**\n     * Creates a cURL handle resource.\n     *\n     * @param RequestInterface $request Request\n     * @param array            $options Transfer options\n     *\n     * @throws \\RuntimeException when an option cannot be applied\n     */\n    public function create(RequestInterface $request, array $options): EasyHandle;\n\n    /**\n     * Release an easy handle, allowing it to be reused or closed.\n     *\n     * This function must call unset on the easy handle's \"handle\" property.\n     */\n    public function release(EasyHandle $easy): void;\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * HTTP handler that uses cURL easy handles as a transport layer.\n *\n * When using the CurlHandler, custom curl options can be specified as an\n * associative array of curl option constants mapping to values in the\n * **curl** key of the \"client\" key of the request.\n *\n * @final\n */\nclass CurlHandler\n{\n    /**\n     * @var CurlFactoryInterface\n     */\n    private $factory;\n\n    /**\n     * Accepts an associative array of options:\n     *\n     * - handle_factory: Optional curl factory used to create cURL handles.\n     *\n     * @param array{handle_factory?: ?CurlFactoryInterface} $options Array of options to use with the handler\n     */\n    public function __construct(array $options = [])\n    {\n        $this->factory = $options['handle_factory']\n            ?? new CurlFactory(3);\n    }\n\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        if (isset($options['delay'])) {\n            \\usleep($options['delay'] * 1000);\n        }\n\n        $easy = $this->factory->create($request, $options);\n        \\curl_exec($easy->handle);\n        $easy->errno = \\curl_errno($easy->handle);\n\n        return CurlFactory::finish($this, $easy, $this->factory);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\Promise;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse GuzzleHttp\\Utils;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Returns an asynchronous response using curl_multi_* functions.\n *\n * When using the CurlMultiHandler, custom curl options can be specified as an\n * associative array of curl option constants mapping to values in the\n * **curl** key of the provided request options.\n *\n * @property resource|\\CurlMultiHandle $_mh Internal use only. Lazy loaded multi-handle.\n *\n * @final\n */\nclass CurlMultiHandler\n{\n    /**\n     * @var CurlFactoryInterface\n     */\n    private $factory;\n\n    /**\n     * @var int\n     */\n    private $selectTimeout;\n\n    /**\n     * @var resource|\\CurlMultiHandle|null the currently executing resource in `curl_multi_exec`.\n     */\n    private $active;\n\n    /**\n     * @var array Request entry handles, indexed by handle id in `addRequest`.\n     *\n     * @see CurlMultiHandler::addRequest\n     */\n    private $handles = [];\n\n    /**\n     * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`.\n     *\n     * @see CurlMultiHandler::addRequest\n     */\n    private $delays = [];\n\n    /**\n     * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()\n     */\n    private $options = [];\n\n    /**\n     * This handler accepts the following options:\n     *\n     * - handle_factory: An optional factory  used to create curl handles\n     * - select_timeout: Optional timeout (in seconds) to block before timing\n     *   out while selecting curl handles. Defaults to 1 second.\n     * - options: An associative array of CURLMOPT_* options and\n     *   corresponding values for curl_multi_setopt()\n     */\n    public function __construct(array $options = [])\n    {\n        $this->factory = $options['handle_factory'] ?? new CurlFactory(50);\n\n        if (isset($options['select_timeout'])) {\n            $this->selectTimeout = $options['select_timeout'];\n        } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {\n            @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option \"select_timeout\" instead.', \\E_USER_DEPRECATED);\n            $this->selectTimeout = (int) $selectTimeout;\n        } else {\n            $this->selectTimeout = 1;\n        }\n\n        $this->options = $options['options'] ?? [];\n    }\n\n    /**\n     * @param string $name\n     *\n     * @return resource|\\CurlMultiHandle\n     *\n     * @throws \\BadMethodCallException when another field as `_mh` will be gotten\n     * @throws \\RuntimeException       when curl can not initialize a multi handle\n     */\n    public function __get($name)\n    {\n        if ($name !== '_mh') {\n            throw new \\BadMethodCallException(\"Can not get other property as '_mh'.\");\n        }\n\n        $multiHandle = \\curl_multi_init();\n\n        if (false === $multiHandle) {\n            throw new \\RuntimeException('Can not initialize curl multi handle.');\n        }\n\n        $this->_mh = $multiHandle;\n\n        foreach ($this->options as $option => $value) {\n            // A warning is raised in case of a wrong option.\n            curl_multi_setopt($this->_mh, $option, $value);\n        }\n\n        return $this->_mh;\n    }\n\n    public function __destruct()\n    {\n        if (isset($this->_mh)) {\n            \\curl_multi_close($this->_mh);\n            unset($this->_mh);\n        }\n    }\n\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        $easy = $this->factory->create($request, $options);\n        $id = (int) $easy->handle;\n\n        $promise = new Promise(\n            [$this, 'execute'],\n            function () use ($id) {\n                return $this->cancel($id);\n            }\n        );\n\n        $this->addRequest(['easy' => $easy, 'deferred' => $promise]);\n\n        return $promise;\n    }\n\n    /**\n     * Ticks the curl event loop.\n     */\n    public function tick(): void\n    {\n        // Add any delayed handles if needed.\n        if ($this->delays) {\n            $currentTime = Utils::currentTime();\n            foreach ($this->delays as $id => $delay) {\n                if ($currentTime >= $delay) {\n                    unset($this->delays[$id]);\n                    \\curl_multi_add_handle(\n                        $this->_mh,\n                        $this->handles[$id]['easy']->handle\n                    );\n                }\n            }\n        }\n\n        // Step through the task queue which may add additional requests.\n        P\\Utils::queue()->run();\n\n        if ($this->active && \\curl_multi_select($this->_mh, $this->selectTimeout) === -1) {\n            // Perform a usleep if a select returns -1.\n            // See: https://bugs.php.net/bug.php?id=61141\n            \\usleep(250);\n        }\n\n        while (\\curl_multi_exec($this->_mh, $this->active) === \\CURLM_CALL_MULTI_PERFORM);\n\n        $this->processMessages();\n    }\n\n    /**\n     * Runs until all outstanding connections have completed.\n     */\n    public function execute(): void\n    {\n        $queue = P\\Utils::queue();\n\n        while ($this->handles || !$queue->isEmpty()) {\n            // If there are no transfers, then sleep for the next delay\n            if (!$this->active && $this->delays) {\n                \\usleep($this->timeToNext());\n            }\n            $this->tick();\n        }\n    }\n\n    private function addRequest(array $entry): void\n    {\n        $easy = $entry['easy'];\n        $id = (int) $easy->handle;\n        $this->handles[$id] = $entry;\n        if (empty($easy->options['delay'])) {\n            \\curl_multi_add_handle($this->_mh, $easy->handle);\n        } else {\n            $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);\n        }\n    }\n\n    /**\n     * Cancels a handle from sending and removes references to it.\n     *\n     * @param int $id Handle ID to cancel and remove.\n     *\n     * @return bool True on success, false on failure.\n     */\n    private function cancel($id): bool\n    {\n        if (!is_int($id)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        // Cannot cancel if it has been processed.\n        if (!isset($this->handles[$id])) {\n            return false;\n        }\n\n        $handle = $this->handles[$id]['easy']->handle;\n        unset($this->delays[$id], $this->handles[$id]);\n        \\curl_multi_remove_handle($this->_mh, $handle);\n        \\curl_close($handle);\n\n        return true;\n    }\n\n    private function processMessages(): void\n    {\n        while ($done = \\curl_multi_info_read($this->_mh)) {\n            if ($done['msg'] !== \\CURLMSG_DONE) {\n                // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216\n                continue;\n            }\n            $id = (int) $done['handle'];\n            \\curl_multi_remove_handle($this->_mh, $done['handle']);\n\n            if (!isset($this->handles[$id])) {\n                // Probably was cancelled.\n                continue;\n            }\n\n            $entry = $this->handles[$id];\n            unset($this->handles[$id], $this->delays[$id]);\n            $entry['easy']->errno = $done['result'];\n            $entry['deferred']->resolve(\n                CurlFactory::finish($this, $entry['easy'], $this->factory)\n            );\n        }\n    }\n\n    private function timeToNext(): int\n    {\n        $currentTime = Utils::currentTime();\n        $nextTime = \\PHP_INT_MAX;\n        foreach ($this->delays as $time) {\n            if ($time < $nextTime) {\n                $nextTime = $time;\n            }\n        }\n\n        return ((int) \\max(0, $nextTime - $currentTime)) * 1000000;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Psr7\\Response;\nuse GuzzleHttp\\Utils;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Represents a cURL easy handle and the data it populates.\n *\n * @internal\n */\nfinal class EasyHandle\n{\n    /**\n     * @var resource|\\CurlHandle cURL resource\n     */\n    public $handle;\n\n    /**\n     * @var StreamInterface Where data is being written\n     */\n    public $sink;\n\n    /**\n     * @var array Received HTTP headers so far\n     */\n    public $headers = [];\n\n    /**\n     * @var ResponseInterface|null Received response (if any)\n     */\n    public $response;\n\n    /**\n     * @var RequestInterface Request being sent\n     */\n    public $request;\n\n    /**\n     * @var array Request options\n     */\n    public $options = [];\n\n    /**\n     * @var int cURL error number (if any)\n     */\n    public $errno = 0;\n\n    /**\n     * @var \\Throwable|null Exception during on_headers (if any)\n     */\n    public $onHeadersException;\n\n    /**\n     * @var \\Exception|null Exception during createResponse (if any)\n     */\n    public $createResponseException;\n\n    /**\n     * Attach a response to the easy handle based on the received headers.\n     *\n     * @throws \\RuntimeException if no headers have been received or the first\n     *                           header line is invalid.\n     */\n    public function createResponse(): void\n    {\n        [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers);\n\n        $normalizedKeys = Utils::normalizeHeaderKeys($headers);\n\n        if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) {\n            $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];\n            unset($headers[$normalizedKeys['content-encoding']]);\n            if (isset($normalizedKeys['content-length'])) {\n                $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];\n\n                $bodyLength = (int) $this->sink->getSize();\n                if ($bodyLength) {\n                    $headers[$normalizedKeys['content-length']] = $bodyLength;\n                } else {\n                    unset($headers[$normalizedKeys['content-length']]);\n                }\n            }\n        }\n\n        // Attach a response to the easy handle with the parsed headers.\n        $this->response = new Response(\n            $status,\n            $headers,\n            $this->sink,\n            $ver,\n            $reason\n        );\n    }\n\n    /**\n     * @param string $name\n     *\n     * @return void\n     *\n     * @throws \\BadMethodCallException\n     */\n    public function __get($name)\n    {\n        $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name;\n        throw new \\BadMethodCallException($msg);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Utils;\n\n/**\n * @internal\n */\nfinal class HeaderProcessor\n{\n    /**\n     * Returns the HTTP version, status code, reason phrase, and headers.\n     *\n     * @param string[] $headers\n     *\n     * @throws \\RuntimeException\n     *\n     * @return array{0:string, 1:int, 2:?string, 3:array}\n     */\n    public static function parseHeaders(array $headers): array\n    {\n        if ($headers === []) {\n            throw new \\RuntimeException('Expected a non-empty array of header data');\n        }\n\n        $parts = \\explode(' ', \\array_shift($headers), 3);\n        $version = \\explode('/', $parts[0])[1] ?? null;\n\n        if ($version === null) {\n            throw new \\RuntimeException('HTTP version missing from header data');\n        }\n\n        $status = $parts[1] ?? null;\n\n        if ($status === null) {\n            throw new \\RuntimeException('HTTP status code missing from header data');\n        }\n\n        return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)];\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\HandlerStack;\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse GuzzleHttp\\TransferStats;\nuse GuzzleHttp\\Utils;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Handler that returns responses or throw exceptions from a queue.\n *\n * @final\n */\nclass MockHandler implements \\Countable\n{\n    /**\n     * @var array\n     */\n    private $queue = [];\n\n    /**\n     * @var RequestInterface|null\n     */\n    private $lastRequest;\n\n    /**\n     * @var array\n     */\n    private $lastOptions = [];\n\n    /**\n     * @var callable|null\n     */\n    private $onFulfilled;\n\n    /**\n     * @var callable|null\n     */\n    private $onRejected;\n\n    /**\n     * Creates a new MockHandler that uses the default handler stack list of\n     * middlewares.\n     *\n     * @param array|null    $queue       Array of responses, callables, or exceptions.\n     * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.\n     * @param callable|null $onRejected  Callback to invoke when the return value is rejected.\n     */\n    public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack\n    {\n        return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));\n    }\n\n    /**\n     * The passed in value must be an array of\n     * {@see \\Psr\\Http\\Message\\ResponseInterface} objects, Exceptions,\n     * callables, or Promises.\n     *\n     * @param array<int, mixed>|null $queue       The parameters to be passed to the append function, as an indexed array.\n     * @param callable|null          $onFulfilled Callback to invoke when the return value is fulfilled.\n     * @param callable|null          $onRejected  Callback to invoke when the return value is rejected.\n     */\n    public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)\n    {\n        $this->onFulfilled = $onFulfilled;\n        $this->onRejected = $onRejected;\n\n        if ($queue) {\n            // array_values included for BC\n            $this->append(...array_values($queue));\n        }\n    }\n\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        if (!$this->queue) {\n            throw new \\OutOfBoundsException('Mock queue is empty');\n        }\n\n        if (isset($options['delay']) && \\is_numeric($options['delay'])) {\n            \\usleep((int) $options['delay'] * 1000);\n        }\n\n        $this->lastRequest = $request;\n        $this->lastOptions = $options;\n        $response = \\array_shift($this->queue);\n\n        if (isset($options['on_headers'])) {\n            if (!\\is_callable($options['on_headers'])) {\n                throw new \\InvalidArgumentException('on_headers must be callable');\n            }\n            try {\n                $options['on_headers']($response);\n            } catch (\\Exception $e) {\n                $msg = 'An error was encountered during the on_headers event';\n                $response = new RequestException($msg, $request, $response, $e);\n            }\n        }\n\n        if (\\is_callable($response)) {\n            $response = $response($request, $options);\n        }\n\n        $response = $response instanceof \\Throwable\n            ? P\\Create::rejectionFor($response)\n            : P\\Create::promiseFor($response);\n\n        return $response->then(\n            function (?ResponseInterface $value) use ($request, $options) {\n                $this->invokeStats($request, $options, $value);\n                if ($this->onFulfilled) {\n                    ($this->onFulfilled)($value);\n                }\n\n                if ($value !== null && isset($options['sink'])) {\n                    $contents = (string) $value->getBody();\n                    $sink = $options['sink'];\n\n                    if (\\is_resource($sink)) {\n                        \\fwrite($sink, $contents);\n                    } elseif (\\is_string($sink)) {\n                        \\file_put_contents($sink, $contents);\n                    } elseif ($sink instanceof StreamInterface) {\n                        $sink->write($contents);\n                    }\n                }\n\n                return $value;\n            },\n            function ($reason) use ($request, $options) {\n                $this->invokeStats($request, $options, null, $reason);\n                if ($this->onRejected) {\n                    ($this->onRejected)($reason);\n                }\n                return P\\Create::rejectionFor($reason);\n            }\n        );\n    }\n\n    /**\n     * Adds one or more variadic requests, exceptions, callables, or promises\n     * to the queue.\n     *\n     * @param mixed ...$values\n     */\n    public function append(...$values): void\n    {\n        foreach ($values as $value) {\n            if ($value instanceof ResponseInterface\n                || $value instanceof \\Throwable\n                || $value instanceof PromiseInterface\n                || \\is_callable($value)\n            ) {\n                $this->queue[] = $value;\n            } else {\n                throw new \\TypeError('Expected a Response, Promise, Throwable or callable. Found ' . Utils::describeType($value));\n            }\n        }\n    }\n\n    /**\n     * Get the last received request.\n     */\n    public function getLastRequest(): ?RequestInterface\n    {\n        return $this->lastRequest;\n    }\n\n    /**\n     * Get the last received request options.\n     */\n    public function getLastOptions(): array\n    {\n        return $this->lastOptions;\n    }\n\n    /**\n     * Returns the number of remaining items in the queue.\n     */\n    public function count(): int\n    {\n        return \\count($this->queue);\n    }\n\n    public function reset(): void\n    {\n        $this->queue = [];\n    }\n\n    /**\n     * @param mixed $reason Promise or reason.\n     */\n    private function invokeStats(\n        RequestInterface $request,\n        array $options,\n        ResponseInterface $response = null,\n        $reason = null\n    ): void {\n        if (isset($options['on_stats'])) {\n            $transferTime = $options['transfer_time'] ?? 0;\n            $stats = new TransferStats($request, $response, $transferTime, $reason);\n            ($options['on_stats'])($stats);\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/Proxy.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse GuzzleHttp\\RequestOptions;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Provides basic proxies for handlers.\n *\n * @final\n */\nclass Proxy\n{\n    /**\n     * Sends synchronous requests to a specific handler while sending all other\n     * requests to another handler.\n     *\n     * @param callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface $default Handler used for normal responses\n     * @param callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface $sync    Handler used for synchronous responses.\n     *\n     * @return callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface Returns the composed handler.\n     */\n    public static function wrapSync(callable $default, callable $sync): callable\n    {\n        return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface {\n            return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options);\n        };\n    }\n\n    /**\n     * Sends streaming requests to a streaming compatible handler while sending\n     * all other requests to a default handler.\n     *\n     * This, for example, could be useful for taking advantage of the\n     * performance benefits of curl while still supporting true streaming\n     * through the StreamHandler.\n     *\n     * @param callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface $default   Handler used for non-streaming responses\n     * @param callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface $streaming Handler used for streaming responses\n     *\n     * @return callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface Returns the composed handler.\n     */\n    public static function wrapStreaming(callable $default, callable $streaming): callable\n    {\n        return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface {\n            return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options);\n        };\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Handler;\n\nuse GuzzleHttp\\Exception\\ConnectException;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\FulfilledPromise;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse GuzzleHttp\\Psr7;\nuse GuzzleHttp\\TransferStats;\nuse GuzzleHttp\\Utils;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\StreamInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * HTTP handler that uses PHP's HTTP stream wrapper.\n *\n * @final\n */\nclass StreamHandler\n{\n    /**\n     * @var array\n     */\n    private $lastHeaders = [];\n\n    /**\n     * Sends an HTTP request.\n     *\n     * @param RequestInterface $request Request to send.\n     * @param array            $options Request transfer options.\n     */\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        // Sleep if there is a delay specified.\n        if (isset($options['delay'])) {\n            \\usleep($options['delay'] * 1000);\n        }\n\n        $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;\n\n        try {\n            // Does not support the expect header.\n            $request = $request->withoutHeader('Expect');\n\n            // Append a content-length header if body size is zero to match\n            // cURL's behavior.\n            if (0 === $request->getBody()->getSize()) {\n                $request = $request->withHeader('Content-Length', '0');\n            }\n\n            return $this->createResponse(\n                $request,\n                $options,\n                $this->createStream($request, $options),\n                $startTime\n            );\n        } catch (\\InvalidArgumentException $e) {\n            throw $e;\n        } catch (\\Exception $e) {\n            // Determine if the error was a networking error.\n            $message = $e->getMessage();\n            // This list can probably get more comprehensive.\n            if (false !== \\strpos($message, 'getaddrinfo') // DNS lookup failed\n                || false !== \\strpos($message, 'Connection refused')\n                || false !== \\strpos($message, \"couldn't connect to host\") // error on HHVM\n                || false !== \\strpos($message, \"connection attempt failed\")\n            ) {\n                $e = new ConnectException($e->getMessage(), $request, $e);\n            } else {\n                $e = RequestException::wrapException($request, $e);\n            }\n            $this->invokeStats($options, $request, $startTime, null, $e);\n\n            return P\\Create::rejectionFor($e);\n        }\n    }\n\n    private function invokeStats(\n        array $options,\n        RequestInterface $request,\n        ?float $startTime,\n        ResponseInterface $response = null,\n        \\Throwable $error = null\n    ): void {\n        if (isset($options['on_stats'])) {\n            $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);\n            ($options['on_stats'])($stats);\n        }\n    }\n\n    /**\n     * @param resource $stream\n     */\n    private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface\n    {\n        $hdrs = $this->lastHeaders;\n        $this->lastHeaders = [];\n\n        try {\n            [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs);\n        } catch (\\Exception $e) {\n            return P\\Create::rejectionFor(\n                new RequestException('An error was encountered while creating the response', $request, null, $e)\n            );\n        }\n\n        [$stream, $headers] = $this->checkDecode($options, $headers, $stream);\n        $stream = Psr7\\Utils::streamFor($stream);\n        $sink = $stream;\n\n        if (\\strcasecmp('HEAD', $request->getMethod())) {\n            $sink = $this->createSink($stream, $options);\n        }\n\n        try {\n            $response = new Psr7\\Response($status, $headers, $sink, $ver, $reason);\n        } catch (\\Exception $e) {\n            return P\\Create::rejectionFor(\n                new RequestException('An error was encountered while creating the response', $request, null, $e)\n            );\n        }\n\n        if (isset($options['on_headers'])) {\n            try {\n                $options['on_headers']($response);\n            } catch (\\Exception $e) {\n                return P\\Create::rejectionFor(\n                    new RequestException('An error was encountered during the on_headers event', $request, $response, $e)\n                );\n            }\n        }\n\n        // Do not drain when the request is a HEAD request because they have\n        // no body.\n        if ($sink !== $stream) {\n            $this->drain($stream, $sink, $response->getHeaderLine('Content-Length'));\n        }\n\n        $this->invokeStats($options, $request, $startTime, $response, null);\n\n        return new FulfilledPromise($response);\n    }\n\n    private function createSink(StreamInterface $stream, array $options): StreamInterface\n    {\n        if (!empty($options['stream'])) {\n            return $stream;\n        }\n\n        $sink = $options['sink'] ?? Psr7\\Utils::tryFopen('php://temp', 'r+');\n\n        return \\is_string($sink) ? new Psr7\\LazyOpenStream($sink, 'w+') : Psr7\\Utils::streamFor($sink);\n    }\n\n    /**\n     * @param resource $stream\n     */\n    private function checkDecode(array $options, array $headers, $stream): array\n    {\n        // Automatically decode responses when instructed.\n        if (!empty($options['decode_content'])) {\n            $normalizedKeys = Utils::normalizeHeaderKeys($headers);\n            if (isset($normalizedKeys['content-encoding'])) {\n                $encoding = $headers[$normalizedKeys['content-encoding']];\n                if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {\n                    $stream = new Psr7\\InflateStream(Psr7\\Utils::streamFor($stream));\n                    $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];\n\n                    // Remove content-encoding header\n                    unset($headers[$normalizedKeys['content-encoding']]);\n\n                    // Fix content-length header\n                    if (isset($normalizedKeys['content-length'])) {\n                        $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];\n                        $length = (int) $stream->getSize();\n                        if ($length === 0) {\n                            unset($headers[$normalizedKeys['content-length']]);\n                        } else {\n                            $headers[$normalizedKeys['content-length']] = [$length];\n                        }\n                    }\n                }\n            }\n        }\n\n        return [$stream, $headers];\n    }\n\n    /**\n     * Drains the source stream into the \"sink\" client option.\n     *\n     * @param string $contentLength Header specifying the amount of\n     *                              data to read.\n     *\n     * @throws \\RuntimeException when the sink option is invalid.\n     */\n    private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface\n    {\n        // If a content-length header is provided, then stop reading once\n        // that number of bytes has been read. This can prevent infinitely\n        // reading from a stream when dealing with servers that do not honor\n        // Connection: Close headers.\n        Psr7\\Utils::copyToStream(\n            $source,\n            $sink,\n            (\\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1\n        );\n\n        $sink->seek(0);\n        $source->close();\n\n        return $sink;\n    }\n\n    /**\n     * Create a resource and check to ensure it was created successfully\n     *\n     * @param callable $callback Callable that returns stream resource\n     *\n     * @return resource\n     *\n     * @throws \\RuntimeException on error\n     */\n    private function createResource(callable $callback)\n    {\n        $errors = [];\n        \\set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool {\n            $errors[] = [\n                'message' => $msg,\n                'file'    => $file,\n                'line'    => $line\n            ];\n            return true;\n        });\n\n        try {\n            $resource = $callback();\n        } finally {\n            \\restore_error_handler();\n        }\n\n        if (!$resource) {\n            $message = 'Error creating resource: ';\n            foreach ($errors as $err) {\n                foreach ($err as $key => $value) {\n                    $message .= \"[$key] $value\" . \\PHP_EOL;\n                }\n            }\n            throw new \\RuntimeException(\\trim($message));\n        }\n\n        return $resource;\n    }\n\n    /**\n     * @return resource\n     */\n    private function createStream(RequestInterface $request, array $options)\n    {\n        static $methods;\n        if (!$methods) {\n            $methods = \\array_flip(\\get_class_methods(__CLASS__));\n        }\n\n        // HTTP/1.1 streams using the PHP stream wrapper require a\n        // Connection: close header\n        if ($request->getProtocolVersion() == '1.1'\n            && !$request->hasHeader('Connection')\n        ) {\n            $request = $request->withHeader('Connection', 'close');\n        }\n\n        // Ensure SSL is verified by default\n        if (!isset($options['verify'])) {\n            $options['verify'] = true;\n        }\n\n        $params = [];\n        $context = $this->getDefaultContext($request);\n\n        if (isset($options['on_headers']) && !\\is_callable($options['on_headers'])) {\n            throw new \\InvalidArgumentException('on_headers must be callable');\n        }\n\n        if (!empty($options)) {\n            foreach ($options as $key => $value) {\n                $method = \"add_{$key}\";\n                if (isset($methods[$method])) {\n                    $this->{$method}($request, $context, $value, $params);\n                }\n            }\n        }\n\n        if (isset($options['stream_context'])) {\n            if (!\\is_array($options['stream_context'])) {\n                throw new \\InvalidArgumentException('stream_context must be an array');\n            }\n            $context = \\array_replace_recursive($context, $options['stream_context']);\n        }\n\n        // Microsoft NTLM authentication only supported with curl handler\n        if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {\n            throw new \\InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');\n        }\n\n        $uri = $this->resolveHost($request, $options);\n\n        $contextResource = $this->createResource(\n            static function () use ($context, $params) {\n                return \\stream_context_create($context, $params);\n            }\n        );\n\n        return $this->createResource(\n            function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) {\n                $resource = @\\fopen((string) $uri, 'r', false, $contextResource);\n                $this->lastHeaders = $http_response_header;\n\n                if (false === $resource) {\n                    throw new ConnectException(sprintf('Connection refused for URI %s', $uri), $request, null, $context);\n                }\n\n                if (isset($options['read_timeout'])) {\n                    $readTimeout = $options['read_timeout'];\n                    $sec = (int) $readTimeout;\n                    $usec = ($readTimeout - $sec) * 100000;\n                    \\stream_set_timeout($resource, $sec, $usec);\n                }\n\n                return $resource;\n            }\n        );\n    }\n\n    private function resolveHost(RequestInterface $request, array $options): UriInterface\n    {\n        $uri = $request->getUri();\n\n        if (isset($options['force_ip_resolve']) && !\\filter_var($uri->getHost(), \\FILTER_VALIDATE_IP)) {\n            if ('v4' === $options['force_ip_resolve']) {\n                $records = \\dns_get_record($uri->getHost(), \\DNS_A);\n                if (false === $records || !isset($records[0]['ip'])) {\n                    throw new ConnectException(\\sprintf(\"Could not resolve IPv4 address for host '%s'\", $uri->getHost()), $request);\n                }\n                return $uri->withHost($records[0]['ip']);\n            }\n            if ('v6' === $options['force_ip_resolve']) {\n                $records = \\dns_get_record($uri->getHost(), \\DNS_AAAA);\n                if (false === $records || !isset($records[0]['ipv6'])) {\n                    throw new ConnectException(\\sprintf(\"Could not resolve IPv6 address for host '%s'\", $uri->getHost()), $request);\n                }\n                return $uri->withHost('[' . $records[0]['ipv6'] . ']');\n            }\n        }\n\n        return $uri;\n    }\n\n    private function getDefaultContext(RequestInterface $request): array\n    {\n        $headers = '';\n        foreach ($request->getHeaders() as $name => $value) {\n            foreach ($value as $val) {\n                $headers .= \"$name: $val\\r\\n\";\n            }\n        }\n\n        $context = [\n            'http' => [\n                'method'           => $request->getMethod(),\n                'header'           => $headers,\n                'protocol_version' => $request->getProtocolVersion(),\n                'ignore_errors'    => true,\n                'follow_location'  => 0,\n            ],\n        ];\n\n        $body = (string) $request->getBody();\n\n        if (!empty($body)) {\n            $context['http']['content'] = $body;\n            // Prevent the HTTP handler from adding a Content-Type header.\n            if (!$request->hasHeader('Content-Type')) {\n                $context['http']['header'] .= \"Content-Type:\\r\\n\";\n            }\n        }\n\n        $context['http']['header'] = \\rtrim($context['http']['header']);\n\n        return $context;\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void\n    {\n        $uri = null;\n\n        if (!\\is_array($value)) {\n            $uri = $value;\n        } else {\n            $scheme = $request->getUri()->getScheme();\n            if (isset($value[$scheme])) {\n                if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {\n                    $uri = $value[$scheme];\n                }\n            }\n        }\n\n        if (!$uri) {\n            return;\n        }\n\n        $parsed = $this->parse_proxy($uri);\n        $options['http']['proxy'] = $parsed['proxy'];\n\n        if ($parsed['auth']) {\n            if (!isset($options['http']['header'])) {\n                $options['http']['header'] = [];\n            }\n            $options['http']['header'] .= \"\\r\\nProxy-Authorization: {$parsed['auth']}\";\n        }\n    }\n\n    /**\n     * Parses the given proxy URL to make it compatible with the format PHP's stream context expects.\n     */\n    private function parse_proxy(string $url): array\n    {\n        $parsed = \\parse_url($url);\n\n        if ($parsed !== false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {\n            if (isset($parsed['host']) && isset($parsed['port'])) {\n                $auth = null;\n                if (isset($parsed['user']) && isset($parsed['pass'])) {\n                    $auth = \\base64_encode(\"{$parsed['user']}:{$parsed['pass']}\");\n                }\n\n                return [\n                    'proxy' => \"tcp://{$parsed['host']}:{$parsed['port']}\",\n                    'auth' => $auth ? \"Basic {$auth}\" : null,\n                ];\n            }\n        }\n\n        // Return proxy as-is.\n        return [\n            'proxy' => $url,\n            'auth' => null,\n        ];\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void\n    {\n        if ($value > 0) {\n            $options['http']['timeout'] = $value;\n        }\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void\n    {\n        if ($value === false) {\n            $options['ssl']['verify_peer'] = false;\n            $options['ssl']['verify_peer_name'] = false;\n\n            return;\n        }\n\n        if (\\is_string($value)) {\n            $options['ssl']['cafile'] = $value;\n            if (!\\file_exists($value)) {\n                throw new \\RuntimeException(\"SSL CA bundle not found: $value\");\n            }\n        } elseif ($value !== true) {\n            throw new \\InvalidArgumentException('Invalid verify request option');\n        }\n\n        $options['ssl']['verify_peer'] = true;\n        $options['ssl']['verify_peer_name'] = true;\n        $options['ssl']['allow_self_signed'] = false;\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void\n    {\n        if (\\is_array($value)) {\n            $options['ssl']['passphrase'] = $value[1];\n            $value = $value[0];\n        }\n\n        if (!\\file_exists($value)) {\n            throw new \\RuntimeException(\"SSL certificate not found: {$value}\");\n        }\n\n        $options['ssl']['local_cert'] = $value;\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void\n    {\n        self::addNotification(\n            $params,\n            static function ($code, $a, $b, $c, $transferred, $total) use ($value) {\n                if ($code == \\STREAM_NOTIFY_PROGRESS) {\n                    // The upload progress cannot be determined. Use 0 for cURL compatibility:\n                    // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html\n                    $value($total, $transferred, 0, 0);\n                }\n            }\n        );\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void\n    {\n        if ($value === false) {\n            return;\n        }\n\n        static $map = [\n            \\STREAM_NOTIFY_CONNECT       => 'CONNECT',\n            \\STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',\n            \\STREAM_NOTIFY_AUTH_RESULT   => 'AUTH_RESULT',\n            \\STREAM_NOTIFY_MIME_TYPE_IS  => 'MIME_TYPE_IS',\n            \\STREAM_NOTIFY_FILE_SIZE_IS  => 'FILE_SIZE_IS',\n            \\STREAM_NOTIFY_REDIRECTED    => 'REDIRECTED',\n            \\STREAM_NOTIFY_PROGRESS      => 'PROGRESS',\n            \\STREAM_NOTIFY_FAILURE       => 'FAILURE',\n            \\STREAM_NOTIFY_COMPLETED     => 'COMPLETED',\n            \\STREAM_NOTIFY_RESOLVE       => 'RESOLVE',\n        ];\n        static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];\n\n        $value = Utils::debugResource($value);\n        $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');\n        self::addNotification(\n            $params,\n            static function (int $code, ...$passed) use ($ident, $value, $map, $args): void {\n                \\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);\n                foreach (\\array_filter($passed) as $i => $v) {\n                    \\fwrite($value, $args[$i] . ': \"' . $v . '\" ');\n                }\n                \\fwrite($value, \"\\n\");\n            }\n        );\n    }\n\n    private static function addNotification(array &$params, callable $notify): void\n    {\n        // Wrap the existing function if needed.\n        if (!isset($params['notification'])) {\n            $params['notification'] = $notify;\n        } else {\n            $params['notification'] = self::callArray([\n                $params['notification'],\n                $notify\n            ]);\n        }\n    }\n\n    private static function callArray(array $functions): callable\n    {\n        return static function (...$args) use ($functions) {\n            foreach ($functions as $fn) {\n                $fn(...$args);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/HandlerStack.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\n/**\n * Creates a composed Guzzle handler function by stacking middlewares on top of\n * an HTTP handler function.\n *\n * @final\n */\nclass HandlerStack\n{\n    /**\n     * @var (callable(RequestInterface, array): PromiseInterface)|null\n     */\n    private $handler;\n\n    /**\n     * @var array{(callable(callable(RequestInterface, array): PromiseInterface): callable), (string|null)}[]\n     */\n    private $stack = [];\n\n    /**\n     * @var (callable(RequestInterface, array): PromiseInterface)|null\n     */\n    private $cached;\n\n    /**\n     * Creates a default handler stack that can be used by clients.\n     *\n     * The returned handler will wrap the provided handler or use the most\n     * appropriate default handler for your system. The returned HandlerStack has\n     * support for cookies, redirects, HTTP error exceptions, and preparing a body\n     * before sending.\n     *\n     * The returned handler stack can be passed to a client in the \"handler\"\n     * option.\n     *\n     * @param (callable(RequestInterface, array): PromiseInterface)|null $handler HTTP handler function to use with the stack. If no\n     *                                                                            handler is provided, the best handler for your\n     *                                                                            system will be utilized.\n     */\n    public static function create(?callable $handler = null): self\n    {\n        $stack = new self($handler ?: Utils::chooseHandler());\n        $stack->push(Middleware::httpErrors(), 'http_errors');\n        $stack->push(Middleware::redirect(), 'allow_redirects');\n        $stack->push(Middleware::cookies(), 'cookies');\n        $stack->push(Middleware::prepareBody(), 'prepare_body');\n\n        return $stack;\n    }\n\n    /**\n     * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler.\n     */\n    public function __construct(callable $handler = null)\n    {\n        $this->handler = $handler;\n    }\n\n    /**\n     * Invokes the handler stack as a composed handler\n     *\n     * @return ResponseInterface|PromiseInterface\n     */\n    public function __invoke(RequestInterface $request, array $options)\n    {\n        $handler = $this->resolve();\n\n        return $handler($request, $options);\n    }\n\n    /**\n     * Dumps a string representation of the stack.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        $depth = 0;\n        $stack = [];\n\n        if ($this->handler !== null) {\n            $stack[] = \"0) Handler: \" . $this->debugCallable($this->handler);\n        }\n\n        $result = '';\n        foreach (\\array_reverse($this->stack) as $tuple) {\n            $depth++;\n            $str = \"{$depth}) Name: '{$tuple[1]}', \";\n            $str .= \"Function: \" . $this->debugCallable($tuple[0]);\n            $result = \"> {$str}\\n{$result}\";\n            $stack[] = $str;\n        }\n\n        foreach (\\array_keys($stack) as $k) {\n            $result .= \"< {$stack[$k]}\\n\";\n        }\n\n        return $result;\n    }\n\n    /**\n     * Set the HTTP handler that actually returns a promise.\n     *\n     * @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and\n     *                                                                     returns a Promise.\n     */\n    public function setHandler(callable $handler): void\n    {\n        $this->handler = $handler;\n        $this->cached = null;\n    }\n\n    /**\n     * Returns true if the builder has a handler.\n     */\n    public function hasHandler(): bool\n    {\n        return $this->handler !== null ;\n    }\n\n    /**\n     * Unshift a middleware to the bottom of the stack.\n     *\n     * @param callable(callable): callable $middleware Middleware function\n     * @param string                       $name       Name to register for this middleware.\n     */\n    public function unshift(callable $middleware, ?string $name = null): void\n    {\n        \\array_unshift($this->stack, [$middleware, $name]);\n        $this->cached = null;\n    }\n\n    /**\n     * Push a middleware to the top of the stack.\n     *\n     * @param callable(callable): callable $middleware Middleware function\n     * @param string                       $name       Name to register for this middleware.\n     */\n    public function push(callable $middleware, string $name = ''): void\n    {\n        $this->stack[] = [$middleware, $name];\n        $this->cached = null;\n    }\n\n    /**\n     * Add a middleware before another middleware by name.\n     *\n     * @param string                       $findName   Middleware to find\n     * @param callable(callable): callable $middleware Middleware function\n     * @param string                       $withName   Name to register for this middleware.\n     */\n    public function before(string $findName, callable $middleware, string $withName = ''): void\n    {\n        $this->splice($findName, $withName, $middleware, true);\n    }\n\n    /**\n     * Add a middleware after another middleware by name.\n     *\n     * @param string                       $findName   Middleware to find\n     * @param callable(callable): callable $middleware Middleware function\n     * @param string                       $withName   Name to register for this middleware.\n     */\n    public function after(string $findName, callable $middleware, string $withName = ''): void\n    {\n        $this->splice($findName, $withName, $middleware, false);\n    }\n\n    /**\n     * Remove a middleware by instance or name from the stack.\n     *\n     * @param callable|string $remove Middleware to remove by instance or name.\n     */\n    public function remove($remove): void\n    {\n        if (!is_string($remove) && !is_callable($remove)) {\n            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);\n        }\n\n        $this->cached = null;\n        $idx = \\is_callable($remove) ? 0 : 1;\n        $this->stack = \\array_values(\\array_filter(\n            $this->stack,\n            static function ($tuple) use ($idx, $remove) {\n                return $tuple[$idx] !== $remove;\n            }\n        ));\n    }\n\n    /**\n     * Compose the middleware and handler into a single callable function.\n     *\n     * @return callable(RequestInterface, array): PromiseInterface\n     */\n    public function resolve(): callable\n    {\n        if ($this->cached === null) {\n            if (($prev = $this->handler) === null) {\n                throw new \\LogicException('No handler has been specified');\n            }\n\n            foreach (\\array_reverse($this->stack) as $fn) {\n                /** @var callable(RequestInterface, array): PromiseInterface $prev */\n                $prev = $fn[0]($prev);\n            }\n\n            $this->cached = $prev;\n        }\n\n        return $this->cached;\n    }\n\n    private function findByName(string $name): int\n    {\n        foreach ($this->stack as $k => $v) {\n            if ($v[1] === $name) {\n                return $k;\n            }\n        }\n\n        throw new \\InvalidArgumentException(\"Middleware not found: $name\");\n    }\n\n    /**\n     * Splices a function into the middleware list at a specific position.\n     */\n    private function splice(string $findName, string $withName, callable $middleware, bool $before): void\n    {\n        $this->cached = null;\n        $idx = $this->findByName($findName);\n        $tuple = [$middleware, $withName];\n\n        if ($before) {\n            if ($idx === 0) {\n                \\array_unshift($this->stack, $tuple);\n            } else {\n                $replacement = [$tuple, $this->stack[$idx]];\n                \\array_splice($this->stack, $idx, 1, $replacement);\n            }\n        } elseif ($idx === \\count($this->stack) - 1) {\n            $this->stack[] = $tuple;\n        } else {\n            $replacement = [$this->stack[$idx], $tuple];\n            \\array_splice($this->stack, $idx, 1, $replacement);\n        }\n    }\n\n    /**\n     * Provides a debug string for a given callable.\n     *\n     * @param callable|string $fn Function to write as a string.\n     */\n    private function debugCallable($fn): string\n    {\n        if (\\is_string($fn)) {\n            return \"callable({$fn})\";\n        }\n\n        if (\\is_array($fn)) {\n            return \\is_string($fn[0])\n                ? \"callable({$fn[0]}::{$fn[1]})\"\n                : \"callable(['\" . \\get_class($fn[0]) . \"', '{$fn[1]}'])\";\n        }\n\n        /** @var object $fn */\n        return 'callable(' . \\spl_object_hash($fn) . ')';\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/MessageFormatter.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse Psr\\Http\\Message\\MessageInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\n/**\n * Formats log messages using variable substitutions for requests, responses,\n * and other transactional data.\n *\n * The following variable substitutions are supported:\n *\n * - {request}:        Full HTTP request message\n * - {response}:       Full HTTP response message\n * - {ts}:             ISO 8601 date in GMT\n * - {date_iso_8601}   ISO 8601 date in GMT\n * - {date_common_log} Apache common log date using the configured timezone.\n * - {host}:           Host of the request\n * - {method}:         Method of the request\n * - {uri}:            URI of the request\n * - {version}:        Protocol version\n * - {target}:         Request target of the request (path + query + fragment)\n * - {hostname}:       Hostname of the machine that sent the request\n * - {code}:           Status code of the response (if available)\n * - {phrase}:         Reason phrase of the response  (if available)\n * - {error}:          Any error messages (if available)\n * - {req_header_*}:   Replace `*` with the lowercased name of a request header to add to the message\n * - {res_header_*}:   Replace `*` with the lowercased name of a response header to add to the message\n * - {req_headers}:    Request headers\n * - {res_headers}:    Response headers\n * - {req_body}:       Request body\n * - {res_body}:       Response body\n *\n * @final\n */\nclass MessageFormatter implements MessageFormatterInterface\n{\n    /**\n     * Apache Common Log Format.\n     *\n     * @link https://httpd.apache.org/docs/2.4/logs.html#common\n     *\n     * @var string\n     */\n    public const CLF = \"{hostname} {req_header_User-Agent} - [{date_common_log}] \\\"{method} {target} HTTP/{version}\\\" {code} {res_header_Content-Length}\";\n    public const DEBUG = \">>>>>>>>\\n{request}\\n<<<<<<<<\\n{response}\\n--------\\n{error}\";\n    public const SHORT = '[{ts}] \"{method} {target} HTTP/{version}\" {code}';\n\n    /**\n     * @var string Template used to format log messages\n     */\n    private $template;\n\n    /**\n     * @param string $template Log message template\n     */\n    public function __construct(?string $template = self::CLF)\n    {\n        $this->template = $template ?: self::CLF;\n    }\n\n    /**\n     * Returns a formatted message string.\n     *\n     * @param RequestInterface       $request  Request that was sent\n     * @param ResponseInterface|null $response Response that was received\n     * @param \\Throwable|null        $error    Exception that was received\n     */\n    public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\\Throwable $error = null): string\n    {\n        $cache = [];\n\n        /** @var string */\n        return \\preg_replace_callback(\n            '/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/',\n            function (array $matches) use ($request, $response, $error, &$cache) {\n                if (isset($cache[$matches[1]])) {\n                    return $cache[$matches[1]];\n                }\n\n                $result = '';\n                switch ($matches[1]) {\n                    case 'request':\n                        $result = Psr7\\Message::toString($request);\n                        break;\n                    case 'response':\n                        $result = $response ? Psr7\\Message::toString($response) : '';\n                        break;\n                    case 'req_headers':\n                        $result = \\trim($request->getMethod()\n                                . ' ' . $request->getRequestTarget())\n                            . ' HTTP/' . $request->getProtocolVersion() . \"\\r\\n\"\n                            . $this->headers($request);\n                        break;\n                    case 'res_headers':\n                        $result = $response ?\n                            \\sprintf(\n                                'HTTP/%s %d %s',\n                                $response->getProtocolVersion(),\n                                $response->getStatusCode(),\n                                $response->getReasonPhrase()\n                            ) . \"\\r\\n\" . $this->headers($response)\n                            : 'NULL';\n                        break;\n                    case 'req_body':\n                        $result = $request->getBody()->__toString();\n                        break;\n                    case 'res_body':\n                        if (!$response instanceof ResponseInterface) {\n                            $result = 'NULL';\n                            break;\n                        }\n\n                        $body = $response->getBody();\n\n                        if (!$body->isSeekable()) {\n                            $result = 'RESPONSE_NOT_LOGGEABLE';\n                            break;\n                        }\n\n                        $result = $response->getBody()->__toString();\n                        break;\n                    case 'ts':\n                    case 'date_iso_8601':\n                        $result = \\gmdate('c');\n                        break;\n                    case 'date_common_log':\n                        $result = \\date('d/M/Y:H:i:s O');\n                        break;\n                    case 'method':\n                        $result = $request->getMethod();\n                        break;\n                    case 'version':\n                        $result = $request->getProtocolVersion();\n                        break;\n                    case 'uri':\n                    case 'url':\n                        $result = $request->getUri()->__toString();\n                        break;\n                    case 'target':\n                        $result = $request->getRequestTarget();\n                        break;\n                    case 'req_version':\n                        $result = $request->getProtocolVersion();\n                        break;\n                    case 'res_version':\n                        $result = $response\n                            ? $response->getProtocolVersion()\n                            : 'NULL';\n                        break;\n                    case 'host':\n                        $result = $request->getHeaderLine('Host');\n                        break;\n                    case 'hostname':\n                        $result = \\gethostname();\n                        break;\n                    case 'code':\n                        $result = $response ? $response->getStatusCode() : 'NULL';\n                        break;\n                    case 'phrase':\n                        $result = $response ? $response->getReasonPhrase() : 'NULL';\n                        break;\n                    case 'error':\n                        $result = $error ? $error->getMessage() : 'NULL';\n                        break;\n                    default:\n                        // handle prefixed dynamic headers\n                        if (\\strpos($matches[1], 'req_header_') === 0) {\n                            $result = $request->getHeaderLine(\\substr($matches[1], 11));\n                        } elseif (\\strpos($matches[1], 'res_header_') === 0) {\n                            $result = $response\n                                ? $response->getHeaderLine(\\substr($matches[1], 11))\n                                : 'NULL';\n                        }\n                }\n\n                $cache[$matches[1]] = $result;\n                return $result;\n            },\n            $this->template\n        );\n    }\n\n    /**\n     * Get headers from message as string\n     */\n    private function headers(MessageInterface $message): string\n    {\n        $result = '';\n        foreach ($message->getHeaders() as $name => $values) {\n            $result .= $name . ': ' . \\implode(', ', $values) . \"\\r\\n\";\n        }\n\n        return \\trim($result);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\ninterface MessageFormatterInterface\n{\n    /**\n     * Returns a formatted message string.\n     *\n     * @param RequestInterface       $request  Request that was sent\n     * @param ResponseInterface|null $response Response that was received\n     * @param \\Throwable|null        $error    Exception that was received\n     */\n    public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\\Throwable $error = null): string;\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Middleware.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Cookie\\CookieJarInterface;\nuse GuzzleHttp\\Exception\\RequestException;\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Log\\LoggerInterface;\n\n/**\n * Functions used to create and wrap handlers with handler middleware.\n */\nfinal class Middleware\n{\n    /**\n     * Middleware that adds cookies to requests.\n     *\n     * The options array must be set to a CookieJarInterface in order to use\n     * cookies. This is typically handled for you by a client.\n     *\n     * @return callable Returns a function that accepts the next handler.\n     */\n    public static function cookies(): callable\n    {\n        return static function (callable $handler): callable {\n            return static function ($request, array $options) use ($handler) {\n                if (empty($options['cookies'])) {\n                    return $handler($request, $options);\n                } elseif (!($options['cookies'] instanceof CookieJarInterface)) {\n                    throw new \\InvalidArgumentException('cookies must be an instance of GuzzleHttp\\Cookie\\CookieJarInterface');\n                }\n                $cookieJar = $options['cookies'];\n                $request = $cookieJar->withCookieHeader($request);\n                return $handler($request, $options)\n                    ->then(\n                        static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface {\n                            $cookieJar->extractCookies($request, $response);\n                            return $response;\n                        }\n                    );\n            };\n        };\n    }\n\n    /**\n     * Middleware that throws exceptions for 4xx or 5xx responses when the\n     * \"http_errors\" request option is set to true.\n     *\n     * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages.\n     *\n     * @return callable(callable): callable Returns a function that accepts the next handler.\n     */\n    public static function httpErrors(BodySummarizerInterface $bodySummarizer = null): callable\n    {\n        return static function (callable $handler) use ($bodySummarizer): callable {\n            return static function ($request, array $options) use ($handler, $bodySummarizer) {\n                if (empty($options['http_errors'])) {\n                    return $handler($request, $options);\n                }\n                return $handler($request, $options)->then(\n                    static function (ResponseInterface $response) use ($request, $bodySummarizer) {\n                        $code = $response->getStatusCode();\n                        if ($code < 400) {\n                            return $response;\n                        }\n                        throw RequestException::create($request, $response, null, [], $bodySummarizer);\n                    }\n                );\n            };\n        };\n    }\n\n    /**\n     * Middleware that pushes history data to an ArrayAccess container.\n     *\n     * @param array|\\ArrayAccess<int, array> $container Container to hold the history (by reference).\n     *\n     * @return callable(callable): callable Returns a function that accepts the next handler.\n     *\n     * @throws \\InvalidArgumentException if container is not an array or ArrayAccess.\n     */\n    public static function history(&$container): callable\n    {\n        if (!\\is_array($container) && !$container instanceof \\ArrayAccess) {\n            throw new \\InvalidArgumentException('history container must be an array or object implementing ArrayAccess');\n        }\n\n        return static function (callable $handler) use (&$container): callable {\n            return static function (RequestInterface $request, array $options) use ($handler, &$container) {\n                return $handler($request, $options)->then(\n                    static function ($value) use ($request, &$container, $options) {\n                        $container[] = [\n                            'request'  => $request,\n                            'response' => $value,\n                            'error'    => null,\n                            'options'  => $options\n                        ];\n                        return $value;\n                    },\n                    static function ($reason) use ($request, &$container, $options) {\n                        $container[] = [\n                            'request'  => $request,\n                            'response' => null,\n                            'error'    => $reason,\n                            'options'  => $options\n                        ];\n                        return P\\Create::rejectionFor($reason);\n                    }\n                );\n            };\n        };\n    }\n\n    /**\n     * Middleware that invokes a callback before and after sending a request.\n     *\n     * The provided listener cannot modify or alter the response. It simply\n     * \"taps\" into the chain to be notified before returning the promise. The\n     * before listener accepts a request and options array, and the after\n     * listener accepts a request, options array, and response promise.\n     *\n     * @param callable $before Function to invoke before forwarding the request.\n     * @param callable $after  Function invoked after forwarding.\n     *\n     * @return callable Returns a function that accepts the next handler.\n     */\n    public static function tap(callable $before = null, callable $after = null): callable\n    {\n        return static function (callable $handler) use ($before, $after): callable {\n            return static function (RequestInterface $request, array $options) use ($handler, $before, $after) {\n                if ($before) {\n                    $before($request, $options);\n                }\n                $response = $handler($request, $options);\n                if ($after) {\n                    $after($request, $options, $response);\n                }\n                return $response;\n            };\n        };\n    }\n\n    /**\n     * Middleware that handles request redirects.\n     *\n     * @return callable Returns a function that accepts the next handler.\n     */\n    public static function redirect(): callable\n    {\n        return static function (callable $handler): RedirectMiddleware {\n            return new RedirectMiddleware($handler);\n        };\n    }\n\n    /**\n     * Middleware that retries requests based on the boolean result of\n     * invoking the provided \"decider\" function.\n     *\n     * If no delay function is provided, a simple implementation of exponential\n     * backoff will be utilized.\n     *\n     * @param callable $decider Function that accepts the number of retries,\n     *                          a request, [response], and [exception] and\n     *                          returns true if the request is to be retried.\n     * @param callable $delay   Function that accepts the number of retries and\n     *                          returns the number of milliseconds to delay.\n     *\n     * @return callable Returns a function that accepts the next handler.\n     */\n    public static function retry(callable $decider, callable $delay = null): callable\n    {\n        return static function (callable $handler) use ($decider, $delay): RetryMiddleware {\n            return new RetryMiddleware($decider, $handler, $delay);\n        };\n    }\n\n    /**\n     * Middleware that logs requests, responses, and errors using a message\n     * formatter.\n     *\n     * @phpstan-param \\Psr\\Log\\LogLevel::* $logLevel  Level at which to log requests.\n     *\n     * @param LoggerInterface                            $logger    Logs messages.\n     * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.\n     * @param string                                     $logLevel  Level at which to log requests.\n     *\n     * @return callable Returns a function that accepts the next handler.\n     */\n    public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable\n    {\n        // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter\n        if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) {\n            throw new \\LogicException(sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class));\n        }\n\n        return static function (callable $handler) use ($logger, $formatter, $logLevel): callable {\n            return static function (RequestInterface $request, array $options = []) use ($handler, $logger, $formatter, $logLevel) {\n                return $handler($request, $options)->then(\n                    static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface {\n                        $message = $formatter->format($request, $response);\n                        $logger->log($logLevel, $message);\n                        return $response;\n                    },\n                    static function ($reason) use ($logger, $request, $formatter): PromiseInterface {\n                        $response = $reason instanceof RequestException ? $reason->getResponse() : null;\n                        $message = $formatter->format($request, $response, P\\Create::exceptionFor($reason));\n                        $logger->error($message);\n                        return P\\Create::rejectionFor($reason);\n                    }\n                );\n            };\n        };\n    }\n\n    /**\n     * This middleware adds a default content-type if possible, a default\n     * content-length or transfer-encoding header, and the expect header.\n     */\n    public static function prepareBody(): callable\n    {\n        return static function (callable $handler): PrepareBodyMiddleware {\n            return new PrepareBodyMiddleware($handler);\n        };\n    }\n\n    /**\n     * Middleware that applies a map function to the request before passing to\n     * the next handler.\n     *\n     * @param callable $fn Function that accepts a RequestInterface and returns\n     *                     a RequestInterface.\n     */\n    public static function mapRequest(callable $fn): callable\n    {\n        return static function (callable $handler) use ($fn): callable {\n            return static function (RequestInterface $request, array $options) use ($handler, $fn) {\n                return $handler($fn($request), $options);\n            };\n        };\n    }\n\n    /**\n     * Middleware that applies a map function to the resolved promise's\n     * response.\n     *\n     * @param callable $fn Function that accepts a ResponseInterface and\n     *                     returns a ResponseInterface.\n     */\n    public static function mapResponse(callable $fn): callable\n    {\n        return static function (callable $handler) use ($fn): callable {\n            return static function (RequestInterface $request, array $options) use ($handler, $fn) {\n                return $handler($request, $options)->then($fn);\n            };\n        };\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Pool.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\EachPromise;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse GuzzleHttp\\Promise\\PromisorInterface;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Sends an iterator of requests concurrently using a capped pool size.\n *\n * The pool will read from an iterator until it is cancelled or until the\n * iterator is consumed. When a request is yielded, the request is sent after\n * applying the \"request_options\" request options (if provided in the ctor).\n *\n * When a function is yielded by the iterator, the function is provided the\n * \"request_options\" array that should be merged on top of any existing\n * options, and the function MUST then return a wait-able promise.\n *\n * @final\n */\nclass Pool implements PromisorInterface\n{\n    /**\n     * @var EachPromise\n     */\n    private $each;\n\n    /**\n     * @param ClientInterface $client   Client used to send the requests.\n     * @param array|\\Iterator $requests Requests or functions that return\n     *                                  requests to send concurrently.\n     * @param array           $config   Associative array of options\n     *                                  - concurrency: (int) Maximum number of requests to send concurrently\n     *                                  - options: Array of request options to apply to each request.\n     *                                  - fulfilled: (callable) Function to invoke when a request completes.\n     *                                  - rejected: (callable) Function to invoke when a request is rejected.\n     */\n    public function __construct(ClientInterface $client, $requests, array $config = [])\n    {\n        if (!isset($config['concurrency'])) {\n            $config['concurrency'] = 25;\n        }\n\n        if (isset($config['options'])) {\n            $opts = $config['options'];\n            unset($config['options']);\n        } else {\n            $opts = [];\n        }\n\n        $iterable = P\\Create::iterFor($requests);\n        $requests = static function () use ($iterable, $client, $opts) {\n            foreach ($iterable as $key => $rfn) {\n                if ($rfn instanceof RequestInterface) {\n                    yield $key => $client->sendAsync($rfn, $opts);\n                } elseif (\\is_callable($rfn)) {\n                    yield $key => $rfn($opts);\n                } else {\n                    throw new \\InvalidArgumentException('Each value yielded by the iterator must be a Psr7\\Http\\Message\\RequestInterface or a callable that returns a promise that fulfills with a Psr7\\Message\\Http\\ResponseInterface object.');\n                }\n            }\n        };\n\n        $this->each = new EachPromise($requests(), $config);\n    }\n\n    /**\n     * Get promise\n     */\n    public function promise(): PromiseInterface\n    {\n        return $this->each->promise();\n    }\n\n    /**\n     * Sends multiple requests concurrently and returns an array of responses\n     * and exceptions that uses the same ordering as the provided requests.\n     *\n     * IMPORTANT: This method keeps every request and response in memory, and\n     * as such, is NOT recommended when sending a large number or an\n     * indeterminate number of requests concurrently.\n     *\n     * @param ClientInterface $client   Client used to send the requests\n     * @param array|\\Iterator $requests Requests to send concurrently.\n     * @param array           $options  Passes through the options available in\n     *                                  {@see \\GuzzleHttp\\Pool::__construct}\n     *\n     * @return array Returns an array containing the response or an exception\n     *               in the same order that the requests were sent.\n     *\n     * @throws \\InvalidArgumentException if the event format is incorrect.\n     */\n    public static function batch(ClientInterface $client, $requests, array $options = []): array\n    {\n        $res = [];\n        self::cmpCallback($options, 'fulfilled', $res);\n        self::cmpCallback($options, 'rejected', $res);\n        $pool = new static($client, $requests, $options);\n        $pool->promise()->wait();\n        \\ksort($res);\n\n        return $res;\n    }\n\n    /**\n     * Execute callback(s)\n     */\n    private static function cmpCallback(array &$options, string $name, array &$results): void\n    {\n        if (!isset($options[$name])) {\n            $options[$name] = static function ($v, $k) use (&$results) {\n                $results[$k] = $v;\n            };\n        } else {\n            $currentFn = $options[$name];\n            $options[$name] = static function ($v, $k) use (&$results, $currentFn) {\n                $currentFn($v, $k);\n                $results[$k] = $v;\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Prepares requests that contain a body, adding the Content-Length,\n * Content-Type, and Expect headers.\n *\n * @final\n */\nclass PrepareBodyMiddleware\n{\n    /**\n     * @var callable(RequestInterface, array): PromiseInterface\n     */\n    private $nextHandler;\n\n    /**\n     * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.\n     */\n    public function __construct(callable $nextHandler)\n    {\n        $this->nextHandler = $nextHandler;\n    }\n\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        $fn = $this->nextHandler;\n\n        // Don't do anything if the request has no body.\n        if ($request->getBody()->getSize() === 0) {\n            return $fn($request, $options);\n        }\n\n        $modify = [];\n\n        // Add a default content-type if possible.\n        if (!$request->hasHeader('Content-Type')) {\n            if ($uri = $request->getBody()->getMetadata('uri')) {\n                if (is_string($uri) && $type = Psr7\\MimeType::fromFilename($uri)) {\n                    $modify['set_headers']['Content-Type'] = $type;\n                }\n            }\n        }\n\n        // Add a default content-length or transfer-encoding header.\n        if (!$request->hasHeader('Content-Length')\n            && !$request->hasHeader('Transfer-Encoding')\n        ) {\n            $size = $request->getBody()->getSize();\n            if ($size !== null) {\n                $modify['set_headers']['Content-Length'] = $size;\n            } else {\n                $modify['set_headers']['Transfer-Encoding'] = 'chunked';\n            }\n        }\n\n        // Add the expect header if needed.\n        $this->addExpectHeader($request, $options, $modify);\n\n        return $fn(Psr7\\Utils::modifyRequest($request, $modify), $options);\n    }\n\n    /**\n     * Add expect header\n     */\n    private function addExpectHeader(RequestInterface $request, array $options, array &$modify): void\n    {\n        // Determine if the Expect header should be used\n        if ($request->hasHeader('Expect')) {\n            return;\n        }\n\n        $expect = $options['expect'] ?? null;\n\n        // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0\n        if ($expect === false || $request->getProtocolVersion() < 1.1) {\n            return;\n        }\n\n        // The expect header is unconditionally enabled\n        if ($expect === true) {\n            $modify['set_headers']['Expect'] = '100-Continue';\n            return;\n        }\n\n        // By default, send the expect header when the payload is > 1mb\n        if ($expect === null) {\n            $expect = 1048576;\n        }\n\n        // Always add if the body cannot be rewound, the size cannot be\n        // determined, or the size is greater than the cutoff threshold\n        $body = $request->getBody();\n        $size = $body->getSize();\n\n        if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {\n            $modify['set_headers']['Expect'] = '100-Continue';\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Exception\\BadResponseException;\nuse GuzzleHttp\\Exception\\TooManyRedirectsException;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Request redirect middleware.\n *\n * Apply this middleware like other middleware using\n * {@see \\GuzzleHttp\\Middleware::redirect()}.\n *\n * @final\n */\nclass RedirectMiddleware\n{\n    public const HISTORY_HEADER = 'X-Guzzle-Redirect-History';\n\n    public const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';\n\n    /**\n     * @var array\n     */\n    public static $defaultSettings = [\n        'max'             => 5,\n        'protocols'       => ['http', 'https'],\n        'strict'          => false,\n        'referer'         => false,\n        'track_redirects' => false,\n    ];\n\n    /**\n     * @var callable(RequestInterface, array): PromiseInterface\n     */\n    private $nextHandler;\n\n    /**\n     * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.\n     */\n    public function __construct(callable $nextHandler)\n    {\n        $this->nextHandler = $nextHandler;\n    }\n\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        $fn = $this->nextHandler;\n\n        if (empty($options['allow_redirects'])) {\n            return $fn($request, $options);\n        }\n\n        if ($options['allow_redirects'] === true) {\n            $options['allow_redirects'] = self::$defaultSettings;\n        } elseif (!\\is_array($options['allow_redirects'])) {\n            throw new \\InvalidArgumentException('allow_redirects must be true, false, or array');\n        } else {\n            // Merge the default settings with the provided settings\n            $options['allow_redirects'] += self::$defaultSettings;\n        }\n\n        if (empty($options['allow_redirects']['max'])) {\n            return $fn($request, $options);\n        }\n\n        return $fn($request, $options)\n            ->then(function (ResponseInterface $response) use ($request, $options) {\n                return $this->checkRedirect($request, $options, $response);\n            });\n    }\n\n    /**\n     * @return ResponseInterface|PromiseInterface\n     */\n    public function checkRedirect(RequestInterface $request, array $options, ResponseInterface $response)\n    {\n        if (\\strpos((string) $response->getStatusCode(), '3') !== 0\n            || !$response->hasHeader('Location')\n        ) {\n            return $response;\n        }\n\n        $this->guardMax($request, $response, $options);\n        $nextRequest = $this->modifyRequest($request, $options, $response);\n\n        if (isset($options['allow_redirects']['on_redirect'])) {\n            ($options['allow_redirects']['on_redirect'])(\n                $request,\n                $response,\n                $nextRequest->getUri()\n            );\n        }\n\n        $promise = $this($nextRequest, $options);\n\n        // Add headers to be able to track history of redirects.\n        if (!empty($options['allow_redirects']['track_redirects'])) {\n            return $this->withTracking(\n                $promise,\n                (string) $nextRequest->getUri(),\n                $response->getStatusCode()\n            );\n        }\n\n        return $promise;\n    }\n\n    /**\n     * Enable tracking on promise.\n     */\n    private function withTracking(PromiseInterface $promise, string $uri, int $statusCode): PromiseInterface\n    {\n        return $promise->then(\n            static function (ResponseInterface $response) use ($uri, $statusCode) {\n                // Note that we are pushing to the front of the list as this\n                // would be an earlier response than what is currently present\n                // in the history header.\n                $historyHeader = $response->getHeader(self::HISTORY_HEADER);\n                $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);\n                \\array_unshift($historyHeader, $uri);\n                \\array_unshift($statusHeader, (string) $statusCode);\n\n                return $response->withHeader(self::HISTORY_HEADER, $historyHeader)\n                                ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);\n            }\n        );\n    }\n\n    /**\n     * Check for too many redirects\n     *\n     * @throws TooManyRedirectsException Too many redirects.\n     */\n    private function guardMax(RequestInterface $request, ResponseInterface $response, array &$options): void\n    {\n        $current = $options['__redirect_count']\n            ?? 0;\n        $options['__redirect_count'] = $current + 1;\n        $max = $options['allow_redirects']['max'];\n\n        if ($options['__redirect_count'] > $max) {\n            throw new TooManyRedirectsException(\"Will not follow more than {$max} redirects\", $request, $response);\n        }\n    }\n\n    public function modifyRequest(RequestInterface $request, array $options, ResponseInterface $response): RequestInterface\n    {\n        // Request modifications to apply.\n        $modify = [];\n        $protocols = $options['allow_redirects']['protocols'];\n\n        // Use a GET request if this is an entity enclosing request and we are\n        // not forcing RFC compliance, but rather emulating what all browsers\n        // would do.\n        $statusCode = $response->getStatusCode();\n        if ($statusCode == 303 ||\n            ($statusCode <= 302 && !$options['allow_redirects']['strict'])\n        ) {\n            $safeMethods = ['GET', 'HEAD', 'OPTIONS'];\n            $requestMethod = $request->getMethod();\n\n            $modify['method'] = in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET';\n            $modify['body'] = '';\n        }\n\n        $uri = $this->redirectUri($request, $response, $protocols);\n        if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {\n            $idnOptions = ($options['idn_conversion'] === true) ? \\IDNA_DEFAULT : $options['idn_conversion'];\n            $uri = Utils::idnUriConvert($uri, $idnOptions);\n        }\n\n        $modify['uri'] = $uri;\n        Psr7\\Message::rewindBody($request);\n\n        // Add the Referer header if it is told to do so and only\n        // add the header if we are not redirecting from https to http.\n        if ($options['allow_redirects']['referer']\n            && $modify['uri']->getScheme() === $request->getUri()->getScheme()\n        ) {\n            $uri = $request->getUri()->withUserInfo('');\n            $modify['set_headers']['Referer'] = (string) $uri;\n        } else {\n            $modify['remove_headers'][] = 'Referer';\n        }\n\n        // Remove Authorization header if host is different.\n        if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {\n            $modify['remove_headers'][] = 'Authorization';\n        }\n\n        return Psr7\\Utils::modifyRequest($request, $modify);\n    }\n\n    /**\n     * Set the appropriate URL on the request based on the location header\n     */\n    private function redirectUri(RequestInterface $request, ResponseInterface $response, array $protocols): UriInterface\n    {\n        $location = Psr7\\UriResolver::resolve(\n            $request->getUri(),\n            new Psr7\\Uri($response->getHeaderLine('Location'))\n        );\n\n        // Ensure that the redirect URI is allowed based on the protocols.\n        if (!\\in_array($location->getScheme(), $protocols)) {\n            throw new BadResponseException(\\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \\implode(', ', $protocols)), $request, $response);\n        }\n\n        return $location;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/RequestOptions.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\n/**\n * This class contains a list of built-in Guzzle request options.\n *\n * More documentation for each option can be found at http://guzzlephp.org/.\n *\n * @link http://docs.guzzlephp.org/en/v6/request-options.html\n */\nfinal class RequestOptions\n{\n    /**\n     * allow_redirects: (bool|array) Controls redirect behavior. Pass false\n     * to disable redirects, pass true to enable redirects, pass an\n     * associative to provide custom redirect settings. Defaults to \"false\".\n     * This option only works if your handler has the RedirectMiddleware. When\n     * passing an associative array, you can provide the following key value\n     * pairs:\n     *\n     * - max: (int, default=5) maximum number of allowed redirects.\n     * - strict: (bool, default=false) Set to true to use strict redirects\n     *   meaning redirect POST requests with POST requests vs. doing what most\n     *   browsers do which is redirect POST requests with GET requests\n     * - referer: (bool, default=false) Set to true to enable the Referer\n     *   header.\n     * - protocols: (array, default=['http', 'https']) Allowed redirect\n     *   protocols.\n     * - on_redirect: (callable) PHP callable that is invoked when a redirect\n     *   is encountered. The callable is invoked with the request, the redirect\n     *   response that was received, and the effective URI. Any return value\n     *   from the on_redirect function is ignored.\n     */\n    public const ALLOW_REDIRECTS = 'allow_redirects';\n\n    /**\n     * auth: (array) Pass an array of HTTP authentication parameters to use\n     * with the request. The array must contain the username in index [0],\n     * the password in index [1], and you can optionally provide a built-in\n     * authentication type in index [2]. Pass null to disable authentication\n     * for a request.\n     */\n    public const AUTH = 'auth';\n\n    /**\n     * body: (resource|string|null|int|float|StreamInterface|callable|\\Iterator)\n     * Body to send in the request.\n     */\n    public const BODY = 'body';\n\n    /**\n     * cert: (string|array) Set to a string to specify the path to a file\n     * containing a PEM formatted SSL client side certificate. If a password\n     * is required, then set cert to an array containing the path to the PEM\n     * file in the first array element followed by the certificate password\n     * in the second array element.\n     */\n    public const CERT = 'cert';\n\n    /**\n     * cookies: (bool|GuzzleHttp\\Cookie\\CookieJarInterface, default=false)\n     * Specifies whether or not cookies are used in a request or what cookie\n     * jar to use or what cookies to send. This option only works if your\n     * handler has the `cookie` middleware. Valid values are `false` and\n     * an instance of {@see \\GuzzleHttp\\Cookie\\CookieJarInterface}.\n     */\n    public const COOKIES = 'cookies';\n\n    /**\n     * connect_timeout: (float, default=0) Float describing the number of\n     * seconds to wait while trying to connect to a server. Use 0 to wait\n     * indefinitely (the default behavior).\n     */\n    public const CONNECT_TIMEOUT = 'connect_timeout';\n\n    /**\n     * debug: (bool|resource) Set to true or set to a PHP stream returned by\n     * fopen()  enable debug output with the HTTP handler used to send a\n     * request.\n     */\n    public const DEBUG = 'debug';\n\n    /**\n     * decode_content: (bool, default=true) Specify whether or not\n     * Content-Encoding responses (gzip, deflate, etc.) are automatically\n     * decoded.\n     */\n    public const DECODE_CONTENT = 'decode_content';\n\n    /**\n     * delay: (int) The amount of time to delay before sending in milliseconds.\n     */\n    public const DELAY = 'delay';\n\n    /**\n     * expect: (bool|integer) Controls the behavior of the\n     * \"Expect: 100-Continue\" header.\n     *\n     * Set to `true` to enable the \"Expect: 100-Continue\" header for all\n     * requests that sends a body. Set to `false` to disable the\n     * \"Expect: 100-Continue\" header for all requests. Set to a number so that\n     * the size of the payload must be greater than the number in order to send\n     * the Expect header. Setting to a number will send the Expect header for\n     * all requests in which the size of the payload cannot be determined or\n     * where the body is not rewindable.\n     *\n     * By default, Guzzle will add the \"Expect: 100-Continue\" header when the\n     * size of the body of a request is greater than 1 MB and a request is\n     * using HTTP/1.1.\n     */\n    public const EXPECT = 'expect';\n\n    /**\n     * form_params: (array) Associative array of form field names to values\n     * where each value is a string or array of strings. Sets the Content-Type\n     * header to application/x-www-form-urlencoded when no Content-Type header\n     * is already present.\n     */\n    public const FORM_PARAMS = 'form_params';\n\n    /**\n     * headers: (array) Associative array of HTTP headers. Each value MUST be\n     * a string or array of strings.\n     */\n    public const HEADERS = 'headers';\n\n    /**\n     * http_errors: (bool, default=true) Set to false to disable exceptions\n     * when a non- successful HTTP response is received. By default,\n     * exceptions will be thrown for 4xx and 5xx responses. This option only\n     * works if your handler has the `httpErrors` middleware.\n     */\n    public const HTTP_ERRORS = 'http_errors';\n\n    /**\n     * idn: (bool|int, default=true) A combination of IDNA_* constants for\n     * idn_to_ascii() PHP's function (see \"options\" parameter). Set to false to\n     * disable IDN support completely, or to true to use the default\n     * configuration (IDNA_DEFAULT constant).\n     */\n    public const IDN_CONVERSION = 'idn_conversion';\n\n    /**\n     * json: (mixed) Adds JSON data to a request. The provided value is JSON\n     * encoded and a Content-Type header of application/json will be added to\n     * the request if no Content-Type header is already present.\n     */\n    public const JSON = 'json';\n\n    /**\n     * multipart: (array) Array of associative arrays, each containing a\n     * required \"name\" key mapping to the form field, name, a required\n     * \"contents\" key mapping to a StreamInterface|resource|string, an\n     * optional \"headers\" associative array of custom headers, and an\n     * optional \"filename\" key mapping to a string to send as the filename in\n     * the part. If no \"filename\" key is present, then no \"filename\" attribute\n     * will be added to the part.\n     */\n    public const MULTIPART = 'multipart';\n\n    /**\n     * on_headers: (callable) A callable that is invoked when the HTTP headers\n     * of the response have been received but the body has not yet begun to\n     * download.\n     */\n    public const ON_HEADERS = 'on_headers';\n\n    /**\n     * on_stats: (callable) allows you to get access to transfer statistics of\n     * a request and access the lower level transfer details of the handler\n     * associated with your client. ``on_stats`` is a callable that is invoked\n     * when a handler has finished sending a request. The callback is invoked\n     * with transfer statistics about the request, the response received, or\n     * the error encountered. Included in the data is the total amount of time\n     * taken to send the request.\n     */\n    public const ON_STATS = 'on_stats';\n\n    /**\n     * progress: (callable) Defines a function to invoke when transfer\n     * progress is made. The function accepts the following positional\n     * arguments: the total number of bytes expected to be downloaded, the\n     * number of bytes downloaded so far, the number of bytes expected to be\n     * uploaded, the number of bytes uploaded so far.\n     */\n    public const PROGRESS = 'progress';\n\n    /**\n     * proxy: (string|array) Pass a string to specify an HTTP proxy, or an\n     * array to specify different proxies for different protocols (where the\n     * key is the protocol and the value is a proxy string).\n     */\n    public const PROXY = 'proxy';\n\n    /**\n     * query: (array|string) Associative array of query string values to add\n     * to the request. This option uses PHP's http_build_query() to create\n     * the string representation. Pass a string value if you need more\n     * control than what this method provides\n     */\n    public const QUERY = 'query';\n\n    /**\n     * sink: (resource|string|StreamInterface) Where the data of the\n     * response is written to. Defaults to a PHP temp stream. Providing a\n     * string will write data to a file by the given name.\n     */\n    public const SINK = 'sink';\n\n    /**\n     * synchronous: (bool) Set to true to inform HTTP handlers that you intend\n     * on waiting on the response. This can be useful for optimizations. Note\n     * that a promise is still returned if you are using one of the async\n     * client methods.\n     */\n    public const SYNCHRONOUS = 'synchronous';\n\n    /**\n     * ssl_key: (array|string) Specify the path to a file containing a private\n     * SSL key in PEM format. If a password is required, then set to an array\n     * containing the path to the SSL key in the first array element followed\n     * by the password required for the certificate in the second element.\n     */\n    public const SSL_KEY = 'ssl_key';\n\n    /**\n     * stream: Set to true to attempt to stream a response rather than\n     * download it all up-front.\n     */\n    public const STREAM = 'stream';\n\n    /**\n     * verify: (bool|string, default=true) Describes the SSL certificate\n     * verification behavior of a request. Set to true to enable SSL\n     * certificate verification using the system CA bundle when available\n     * (the default). Set to false to disable certificate verification (this\n     * is insecure!). Set to a string to provide the path to a CA bundle on\n     * disk to enable verification using a custom certificate.\n     */\n    public const VERIFY = 'verify';\n\n    /**\n     * timeout: (float, default=0) Float describing the timeout of the\n     * request in seconds. Use 0 to wait indefinitely (the default behavior).\n     */\n    public const TIMEOUT = 'timeout';\n\n    /**\n     * read_timeout: (float, default=default_socket_timeout ini setting) Float describing\n     * the body read timeout, for stream requests.\n     */\n    public const READ_TIMEOUT = 'read_timeout';\n\n    /**\n     * version: (float) Specifies the HTTP protocol version to attempt to use.\n     */\n    public const VERSION = 'version';\n\n    /**\n     * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol\n     */\n    public const FORCE_IP_RESOLVE = 'force_ip_resolve';\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/RetryMiddleware.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Promise as P;\nuse GuzzleHttp\\Promise\\PromiseInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\n/**\n * Middleware that retries requests based on the boolean result of\n * invoking the provided \"decider\" function.\n *\n * @final\n */\nclass RetryMiddleware\n{\n    /**\n     * @var callable(RequestInterface, array): PromiseInterface\n     */\n    private $nextHandler;\n\n    /**\n     * @var callable\n     */\n    private $decider;\n\n    /**\n     * @var callable(int)\n     */\n    private $delay;\n\n    /**\n     * @param callable                                            $decider     Function that accepts the number of retries,\n     *                                                                         a request, [response], and [exception] and\n     *                                                                         returns true if the request is to be\n     *                                                                         retried.\n     * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.\n     * @param (callable(int): int)|null                           $delay       Function that accepts the number of retries\n     *                                                                         and returns the number of\n     *                                                                         milliseconds to delay.\n     */\n    public function __construct(callable $decider, callable $nextHandler, callable $delay = null)\n    {\n        $this->decider = $decider;\n        $this->nextHandler = $nextHandler;\n        $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';\n    }\n\n    /**\n     * Default exponential backoff delay function.\n     *\n     * @return int milliseconds.\n     */\n    public static function exponentialDelay(int $retries): int\n    {\n        return (int) \\pow(2, $retries - 1) * 1000;\n    }\n\n    public function __invoke(RequestInterface $request, array $options): PromiseInterface\n    {\n        if (!isset($options['retries'])) {\n            $options['retries'] = 0;\n        }\n\n        $fn = $this->nextHandler;\n        return $fn($request, $options)\n            ->then(\n                $this->onFulfilled($request, $options),\n                $this->onRejected($request, $options)\n            );\n    }\n\n    /**\n     * Execute fulfilled closure\n     */\n    private function onFulfilled(RequestInterface $request, array $options): callable\n    {\n        return function ($value) use ($request, $options) {\n            if (!($this->decider)(\n                $options['retries'],\n                $request,\n                $value,\n                null\n            )) {\n                return $value;\n            }\n            return $this->doRetry($request, $options, $value);\n        };\n    }\n\n    /**\n     * Execute rejected closure\n     */\n    private function onRejected(RequestInterface $req, array $options): callable\n    {\n        return function ($reason) use ($req, $options) {\n            if (!($this->decider)(\n                $options['retries'],\n                $req,\n                null,\n                $reason\n            )) {\n                return P\\Create::rejectionFor($reason);\n            }\n            return $this->doRetry($req, $options);\n        };\n    }\n\n    private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface\n    {\n        $options['delay'] = ($this->delay)(++$options['retries'], $response);\n\n        return $this($request, $options);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/TransferStats.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Represents data at the point after it was transferred either successfully\n * or after a network error.\n */\nfinal class TransferStats\n{\n    /**\n     * @var RequestInterface\n     */\n    private $request;\n\n    /**\n     * @var ResponseInterface|null\n     */\n    private $response;\n\n    /**\n     * @var float|null\n     */\n    private $transferTime;\n\n    /**\n     * @var array\n     */\n    private $handlerStats;\n\n    /**\n     * @var mixed|null\n     */\n    private $handlerErrorData;\n\n    /**\n     * @param RequestInterface       $request          Request that was sent.\n     * @param ResponseInterface|null $response         Response received (if any)\n     * @param float|null             $transferTime     Total handler transfer time.\n     * @param mixed                  $handlerErrorData Handler error data.\n     * @param array                  $handlerStats     Handler specific stats.\n     */\n    public function __construct(\n        RequestInterface $request,\n        ?ResponseInterface $response = null,\n        ?float $transferTime = null,\n        $handlerErrorData = null,\n        array $handlerStats = []\n    ) {\n        $this->request = $request;\n        $this->response = $response;\n        $this->transferTime = $transferTime;\n        $this->handlerErrorData = $handlerErrorData;\n        $this->handlerStats = $handlerStats;\n    }\n\n    public function getRequest(): RequestInterface\n    {\n        return $this->request;\n    }\n\n    /**\n     * Returns the response that was received (if any).\n     */\n    public function getResponse(): ?ResponseInterface\n    {\n        return $this->response;\n    }\n\n    /**\n     * Returns true if a response was received.\n     */\n    public function hasResponse(): bool\n    {\n        return $this->response !== null;\n    }\n\n    /**\n     * Gets handler specific error data.\n     *\n     * This might be an exception, a integer representing an error code, or\n     * anything else. Relying on this value assumes that you know what handler\n     * you are using.\n     *\n     * @return mixed\n     */\n    public function getHandlerErrorData()\n    {\n        return $this->handlerErrorData;\n    }\n\n    /**\n     * Get the effective URI the request was sent to.\n     */\n    public function getEffectiveUri(): UriInterface\n    {\n        return $this->request->getUri();\n    }\n\n    /**\n     * Get the estimated time the request was being transferred by the handler.\n     *\n     * @return float|null Time in seconds.\n     */\n    public function getTransferTime(): ?float\n    {\n        return $this->transferTime;\n    }\n\n    /**\n     * Gets an array of all of the handler specific transfer data.\n     */\n    public function getHandlerStats(): array\n    {\n        return $this->handlerStats;\n    }\n\n    /**\n     * Get a specific handler statistic from the handler by name.\n     *\n     * @param string $stat Handler specific transfer stat to retrieve.\n     *\n     * @return mixed|null\n     */\n    public function getHandlerStat(string $stat)\n    {\n        return $this->handlerStats[$stat] ?? null;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/Utils.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\nuse GuzzleHttp\\Exception\\InvalidArgumentException;\nuse GuzzleHttp\\Handler\\CurlHandler;\nuse GuzzleHttp\\Handler\\CurlMultiHandler;\nuse GuzzleHttp\\Handler\\Proxy;\nuse GuzzleHttp\\Handler\\StreamHandler;\nuse Psr\\Http\\Message\\UriInterface;\n\nfinal class Utils\n{\n    /**\n     * Debug function used to describe the provided value type and class.\n     *\n     * @param mixed $input\n     *\n     * @return string Returns a string containing the type of the variable and\n     *                if a class is provided, the class name.\n     */\n    public static function describeType($input): string\n    {\n        switch (\\gettype($input)) {\n            case 'object':\n                return 'object(' . \\get_class($input) . ')';\n            case 'array':\n                return 'array(' . \\count($input) . ')';\n            default:\n                \\ob_start();\n                \\var_dump($input);\n                // normalize float vs double\n                /** @var string $varDumpContent */\n                $varDumpContent = \\ob_get_clean();\n\n                return \\str_replace('double(', 'float(', \\rtrim($varDumpContent));\n        }\n    }\n\n    /**\n     * Parses an array of header lines into an associative array of headers.\n     *\n     * @param iterable $lines Header lines array of strings in the following\n     *                        format: \"Name: Value\"\n     */\n    public static function headersFromLines(iterable $lines): array\n    {\n        $headers = [];\n\n        foreach ($lines as $line) {\n            $parts = \\explode(':', $line, 2);\n            $headers[\\trim($parts[0])][] = isset($parts[1]) ? \\trim($parts[1]) : null;\n        }\n\n        return $headers;\n    }\n\n    /**\n     * Returns a debug stream based on the provided variable.\n     *\n     * @param mixed $value Optional value\n     *\n     * @return resource\n     */\n    public static function debugResource($value = null)\n    {\n        if (\\is_resource($value)) {\n            return $value;\n        }\n        if (\\defined('STDOUT')) {\n            return \\STDOUT;\n        }\n\n        return \\GuzzleHttp\\Psr7\\Utils::tryFopen('php://output', 'w');\n    }\n\n    /**\n     * Chooses and creates a default handler to use based on the environment.\n     *\n     * The returned handler is not wrapped by any default middlewares.\n     *\n     * @throws \\RuntimeException if no viable Handler is available.\n     *\n     * @return callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface Returns the best handler for the given system.\n     */\n    public static function chooseHandler(): callable\n    {\n        $handler = null;\n        if (\\function_exists('curl_multi_exec') && \\function_exists('curl_exec')) {\n            $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());\n        } elseif (\\function_exists('curl_exec')) {\n            $handler = new CurlHandler();\n        } elseif (\\function_exists('curl_multi_exec')) {\n            $handler = new CurlMultiHandler();\n        }\n\n        if (\\ini_get('allow_url_fopen')) {\n            $handler = $handler\n                ? Proxy::wrapStreaming($handler, new StreamHandler())\n                : new StreamHandler();\n        } elseif (!$handler) {\n            throw new \\RuntimeException('GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.');\n        }\n\n        return $handler;\n    }\n\n    /**\n     * Get the default User-Agent string to use with Guzzle.\n     */\n    public static function defaultUserAgent(): string\n    {\n        return sprintf('GuzzleHttp/%d', ClientInterface::MAJOR_VERSION);\n    }\n\n    /**\n     * Returns the default cacert bundle for the current system.\n     *\n     * First, the openssl.cafile and curl.cainfo php.ini settings are checked.\n     * If those settings are not configured, then the common locations for\n     * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X\n     * and Windows are checked. If any of these file locations are found on\n     * disk, they will be utilized.\n     *\n     * Note: the result of this function is cached for subsequent calls.\n     *\n     * @throws \\RuntimeException if no bundle can be found.\n     *\n     * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+.\n     */\n    public static function defaultCaBundle(): string\n    {\n        static $cached = null;\n        static $cafiles = [\n            // Red Hat, CentOS, Fedora (provided by the ca-certificates package)\n            '/etc/pki/tls/certs/ca-bundle.crt',\n            // Ubuntu, Debian (provided by the ca-certificates package)\n            '/etc/ssl/certs/ca-certificates.crt',\n            // FreeBSD (provided by the ca_root_nss package)\n            '/usr/local/share/certs/ca-root-nss.crt',\n            // SLES 12 (provided by the ca-certificates package)\n            '/var/lib/ca-certificates/ca-bundle.pem',\n            // OS X provided by homebrew (using the default path)\n            '/usr/local/etc/openssl/cert.pem',\n            // Google app engine\n            '/etc/ca-certificates.crt',\n            // Windows?\n            'C:\\\\windows\\\\system32\\\\curl-ca-bundle.crt',\n            'C:\\\\windows\\\\curl-ca-bundle.crt',\n        ];\n\n        if ($cached) {\n            return $cached;\n        }\n\n        if ($ca = \\ini_get('openssl.cafile')) {\n            return $cached = $ca;\n        }\n\n        if ($ca = \\ini_get('curl.cainfo')) {\n            return $cached = $ca;\n        }\n\n        foreach ($cafiles as $filename) {\n            if (\\file_exists($filename)) {\n                return $cached = $filename;\n            }\n        }\n\n        throw new \\RuntimeException(\n            <<< EOT\nNo system CA bundle could be found in any of the the common system locations.\nPHP versions earlier than 5.6 are not properly configured to use the system's\nCA bundle by default. In order to verify peer certificates, you will need to\nsupply the path on disk to a certificate bundle to the 'verify' request\noption: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not\nneed a specific certificate bundle, then Mozilla provides a commonly used CA\nbundle which can be downloaded here (provided by the maintainer of cURL):\nhttps://curl.haxx.se/ca/cacert.pem. Once\nyou have a CA bundle available on disk, you can set the 'openssl.cafile' PHP\nini setting to point to the path to the file, allowing you to omit the 'verify'\nrequest option. See https://curl.haxx.se/docs/sslcerts.html for more\ninformation.\nEOT\n        );\n    }\n\n    /**\n     * Creates an associative array of lowercase header names to the actual\n     * header casing.\n     */\n    public static function normalizeHeaderKeys(array $headers): array\n    {\n        $result = [];\n        foreach (\\array_keys($headers) as $key) {\n            $result[\\strtolower($key)] = $key;\n        }\n\n        return $result;\n    }\n\n    /**\n     * Returns true if the provided host matches any of the no proxy areas.\n     *\n     * This method will strip a port from the host if it is present. Each pattern\n     * can be matched with an exact match (e.g., \"foo.com\" == \"foo.com\") or a\n     * partial match: (e.g., \"foo.com\" == \"baz.foo.com\" and \".foo.com\" ==\n     * \"baz.foo.com\", but \".foo.com\" != \"foo.com\").\n     *\n     * Areas are matched in the following cases:\n     * 1. \"*\" (without quotes) always matches any hosts.\n     * 2. An exact match.\n     * 3. The area starts with \".\" and the area is the last part of the host. e.g.\n     *    '.mit.edu' will match any host that ends with '.mit.edu'.\n     *\n     * @param string   $host         Host to check against the patterns.\n     * @param string[] $noProxyArray An array of host patterns.\n     *\n     * @throws InvalidArgumentException\n     */\n    public static function isHostInNoProxy(string $host, array $noProxyArray): bool\n    {\n        if (\\strlen($host) === 0) {\n            throw new InvalidArgumentException('Empty host provided');\n        }\n\n        // Strip port if present.\n        [$host] = \\explode(':', $host, 2);\n\n        foreach ($noProxyArray as $area) {\n            // Always match on wildcards.\n            if ($area === '*') {\n                return true;\n            }\n\n            if (empty($area)) {\n                // Don't match on empty values.\n                continue;\n            }\n\n            if ($area === $host) {\n                // Exact matches.\n                return true;\n            }\n            // Special match if the area when prefixed with \".\". Remove any\n            // existing leading \".\" and add a new leading \".\".\n            $area = '.' . \\ltrim($area, '.');\n            if (\\substr($host, -(\\strlen($area))) === $area) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Wrapper for json_decode that throws when an error occurs.\n     *\n     * @param string $json    JSON data to parse\n     * @param bool   $assoc   When true, returned objects will be converted\n     *                        into associative arrays.\n     * @param int    $depth   User specified recursion depth.\n     * @param int    $options Bitmask of JSON decode options.\n     *\n     * @return object|array|string|int|float|bool|null\n     *\n     * @throws InvalidArgumentException if the JSON cannot be decoded.\n     *\n     * @link https://www.php.net/manual/en/function.json-decode.php\n     */\n    public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)\n    {\n        $data = \\json_decode($json, $assoc, $depth, $options);\n        if (\\JSON_ERROR_NONE !== \\json_last_error()) {\n            throw new InvalidArgumentException('json_decode error: ' . \\json_last_error_msg());\n        }\n\n        return $data;\n    }\n\n    /**\n     * Wrapper for JSON encoding that throws when an error occurs.\n     *\n     * @param mixed $value   The value being encoded\n     * @param int   $options JSON encode option bitmask\n     * @param int   $depth   Set the maximum depth. Must be greater than zero.\n     *\n     * @throws InvalidArgumentException if the JSON cannot be encoded.\n     *\n     * @link https://www.php.net/manual/en/function.json-encode.php\n     */\n    public static function jsonEncode($value, int $options = 0, int $depth = 512): string\n    {\n        $json = \\json_encode($value, $options, $depth);\n        if (\\JSON_ERROR_NONE !== \\json_last_error()) {\n            throw new InvalidArgumentException('json_encode error: ' . \\json_last_error_msg());\n        }\n\n        /** @var string */\n        return $json;\n    }\n\n    /**\n     * Wrapper for the hrtime() or microtime() functions\n     * (depending on the PHP version, one of the two is used)\n     *\n     * @return float UNIX timestamp\n     *\n     * @internal\n     */\n    public static function currentTime(): float\n    {\n        return (float) \\function_exists('hrtime') ? \\hrtime(true) / 1e9 : \\microtime(true);\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     *\n     * @internal\n     */\n    public static function idnUriConvert(UriInterface $uri, int $options = 0): UriInterface\n    {\n        if ($uri->getHost()) {\n            $asciiHost = self::idnToAsci($uri->getHost(), $options, $info);\n            if ($asciiHost === false) {\n                $errorBitSet = $info['errors'] ?? 0;\n\n                $errorConstants = array_filter(array_keys(get_defined_constants()), static function (string $name): bool {\n                    return substr($name, 0, 11) === 'IDNA_ERROR_';\n                });\n\n                $errors = [];\n                foreach ($errorConstants as $errorConstant) {\n                    if ($errorBitSet & constant($errorConstant)) {\n                        $errors[] = $errorConstant;\n                    }\n                }\n\n                $errorMessage = 'IDN conversion failed';\n                if ($errors) {\n                    $errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';\n                }\n\n                throw new InvalidArgumentException($errorMessage);\n            }\n            if ($uri->getHost() !== $asciiHost) {\n                // Replace URI only if the ASCII version is different\n                $uri = $uri->withHost($asciiHost);\n            }\n        }\n\n        return $uri;\n    }\n\n    /**\n     * @internal\n     */\n    public static function getenv(string $name): ?string\n    {\n        if (isset($_SERVER[$name])) {\n            return (string) $_SERVER[$name];\n        }\n\n        if (\\PHP_SAPI === 'cli' && ($value = \\getenv($name)) !== false && $value !== null) {\n            return (string) $value;\n        }\n\n        return null;\n    }\n\n    /**\n     * @return string|false\n     */\n    private static function idnToAsci(string $domain, int $options, ?array &$info = [])\n    {\n        if (\\function_exists('idn_to_ascii') && \\defined('INTL_IDNA_VARIANT_UTS46')) {\n            return \\idn_to_ascii($domain, $options, \\INTL_IDNA_VARIANT_UTS46, $info);\n        }\n\n        throw new \\Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old');\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/functions.php",
    "content": "<?php\n\nnamespace GuzzleHttp;\n\n/**\n * Debug function used to describe the provided value type and class.\n *\n * @param mixed $input Any type of variable to describe the type of. This\n *                     parameter misses a typehint because of that.\n *\n * @return string Returns a string containing the type of the variable and\n *                if a class is provided, the class name.\n *\n * @deprecated describe_type will be removed in guzzlehttp/guzzle:8.0. Use Utils::describeType instead.\n */\nfunction describe_type($input): string\n{\n    return Utils::describeType($input);\n}\n\n/**\n * Parses an array of header lines into an associative array of headers.\n *\n * @param iterable $lines Header lines array of strings in the following\n *                        format: \"Name: Value\"\n *\n * @deprecated headers_from_lines will be removed in guzzlehttp/guzzle:8.0. Use Utils::headersFromLines instead.\n */\nfunction headers_from_lines(iterable $lines): array\n{\n    return Utils::headersFromLines($lines);\n}\n\n/**\n * Returns a debug stream based on the provided variable.\n *\n * @param mixed $value Optional value\n *\n * @return resource\n *\n * @deprecated debug_resource will be removed in guzzlehttp/guzzle:8.0. Use Utils::debugResource instead.\n */\nfunction debug_resource($value = null)\n{\n    return Utils::debugResource($value);\n}\n\n/**\n * Chooses and creates a default handler to use based on the environment.\n *\n * The returned handler is not wrapped by any default middlewares.\n *\n * @throws \\RuntimeException if no viable Handler is available.\n *\n * @return callable(\\Psr\\Http\\Message\\RequestInterface, array): \\GuzzleHttp\\Promise\\PromiseInterface Returns the best handler for the given system.\n *\n * @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead.\n */\nfunction choose_handler(): callable\n{\n    return Utils::chooseHandler();\n}\n\n/**\n * Get the default User-Agent string to use with Guzzle.\n *\n * @deprecated default_user_agent will be removed in guzzlehttp/guzzle:8.0. Use Utils::defaultUserAgent instead.\n */\nfunction default_user_agent(): string\n{\n    return Utils::defaultUserAgent();\n}\n\n/**\n * Returns the default cacert bundle for the current system.\n *\n * First, the openssl.cafile and curl.cainfo php.ini settings are checked.\n * If those settings are not configured, then the common locations for\n * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X\n * and Windows are checked. If any of these file locations are found on\n * disk, they will be utilized.\n *\n * Note: the result of this function is cached for subsequent calls.\n *\n * @throws \\RuntimeException if no bundle can be found.\n *\n * @deprecated default_ca_bundle will be removed in guzzlehttp/guzzle:8.0. This function is not needed in PHP 5.6+.\n */\nfunction default_ca_bundle(): string\n{\n    return Utils::defaultCaBundle();\n}\n\n/**\n * Creates an associative array of lowercase header names to the actual\n * header casing.\n *\n * @deprecated normalize_header_keys will be removed in guzzlehttp/guzzle:8.0. Use Utils::normalizeHeaderKeys instead.\n */\nfunction normalize_header_keys(array $headers): array\n{\n    return Utils::normalizeHeaderKeys($headers);\n}\n\n/**\n * Returns true if the provided host matches any of the no proxy areas.\n *\n * This method will strip a port from the host if it is present. Each pattern\n * can be matched with an exact match (e.g., \"foo.com\" == \"foo.com\") or a\n * partial match: (e.g., \"foo.com\" == \"baz.foo.com\" and \".foo.com\" ==\n * \"baz.foo.com\", but \".foo.com\" != \"foo.com\").\n *\n * Areas are matched in the following cases:\n * 1. \"*\" (without quotes) always matches any hosts.\n * 2. An exact match.\n * 3. The area starts with \".\" and the area is the last part of the host. e.g.\n *    '.mit.edu' will match any host that ends with '.mit.edu'.\n *\n * @param string   $host         Host to check against the patterns.\n * @param string[] $noProxyArray An array of host patterns.\n *\n * @throws Exception\\InvalidArgumentException\n *\n * @deprecated is_host_in_noproxy will be removed in guzzlehttp/guzzle:8.0. Use Utils::isHostInNoProxy instead.\n */\nfunction is_host_in_noproxy(string $host, array $noProxyArray): bool\n{\n    return Utils::isHostInNoProxy($host, $noProxyArray);\n}\n\n/**\n * Wrapper for json_decode that throws when an error occurs.\n *\n * @param string $json    JSON data to parse\n * @param bool   $assoc   When true, returned objects will be converted\n *                        into associative arrays.\n * @param int    $depth   User specified recursion depth.\n * @param int    $options Bitmask of JSON decode options.\n *\n * @return object|array|string|int|float|bool|null\n *\n * @throws Exception\\InvalidArgumentException if the JSON cannot be decoded.\n *\n * @link https://www.php.net/manual/en/function.json-decode.php\n * @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead.\n */\nfunction json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)\n{\n    return Utils::jsonDecode($json, $assoc, $depth, $options);\n}\n\n/**\n * Wrapper for JSON encoding that throws when an error occurs.\n *\n * @param mixed $value   The value being encoded\n * @param int   $options JSON encode option bitmask\n * @param int   $depth   Set the maximum depth. Must be greater than zero.\n *\n * @throws Exception\\InvalidArgumentException if the JSON cannot be encoded.\n *\n * @link https://www.php.net/manual/en/function.json-encode.php\n * @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead.\n */\nfunction json_encode($value, int $options = 0, int $depth = 512): string\n{\n    return Utils::jsonEncode($value, $options, $depth);\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/guzzle/src/functions_include.php",
    "content": "<?php\n\n// Don't redefine the functions if included multiple times.\nif (!\\function_exists('GuzzleHttp\\describe_type')) {\n    require __DIR__ . '/functions.php';\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/CHANGELOG.md",
    "content": "# CHANGELOG\n\n## 1.5.1 - 2021-10-22\n\n### Fixed\n\n- Revert \"Call handler when waiting on fulfilled/rejected Promise\"\n- Fix pool memory leak when empty array of promises provided\n\n## 1.5.0 - 2021-10-07\n\n### Changed\n\n- Call handler when waiting on fulfilled/rejected Promise\n\n### Fixed\n\n- Fix manually settle promises generated with Utils::task\n\n## 1.4.1 - 2021-02-18\n\n### Fixed\n\n- Fixed `each_limit` skipping promises and failing\n\n## 1.4.0 - 2020-09-30\n\n### Added\n\n- Support for PHP 8\n- Optional `$recursive` flag to `all`\n- Replaced functions by static methods\n\n### Fixed\n\n- Fix empty `each` processing\n- Fix promise handling for Iterators of non-unique keys\n- Fixed `method_exists` crashes on PHP 8\n- Memory leak on exceptions\n\n\n## 1.3.1 - 2016-12-20\n\n### Fixed\n\n- `wait()` foreign promise compatibility\n\n\n## 1.3.0 - 2016-11-18\n\n### Added\n\n- Adds support for custom task queues.\n\n### Fixed\n\n- Fixed coroutine promise memory leak.\n\n\n## 1.2.0 - 2016-05-18\n\n### Changed\n\n- Update to now catch `\\Throwable` on PHP 7+\n\n\n## 1.1.0 - 2016-03-07\n\n### Changed\n\n- Update EachPromise to prevent recurring on a iterator when advancing, as this\n  could trigger fatal generator errors.\n- Update Promise to allow recursive waiting without unwrapping exceptions.\n\n\n## 1.0.3 - 2015-10-15\n\n### Changed\n\n- Update EachPromise to immediately resolve when the underlying promise iterator\n  is empty. Previously, such a promise would throw an exception when its `wait`\n  function was called.\n\n\n## 1.0.2 - 2015-05-15\n\n### Changed\n\n- Conditionally require functions.php.\n\n\n## 1.0.1 - 2015-06-24\n\n### Changed\n\n- Updating EachPromise to call next on the underlying promise iterator as late\n  as possible to ensure that generators that generate new requests based on\n  callbacks are not iterated until after callbacks are invoked.\n\n\n## 1.0.0 - 2015-05-12\n\n- Initial release\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Michael Dowling <mtdowling@gmail.com>\nCopyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk>\nCopyright (c) 2017 Tobias Schultze <webmaster@tubo-world.de>\nCopyright (c) 2020 Tobias Nyholm <tobias.nyholm@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/Makefile",
    "content": "all: clean test\n\ntest:\n\tvendor/bin/phpunit\n\ncoverage:\n\tvendor/bin/phpunit --coverage-html=artifacts/coverage\n\nview-coverage:\n\topen artifacts/coverage/index.html\n\nclean:\n\trm -rf artifacts/*\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/README.md",
    "content": "# Guzzle Promises\n\n[Promises/A+](https://promisesaplus.com/) implementation that handles promise\nchaining and resolution iteratively, allowing for \"infinite\" promise chaining\nwhile keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)\nfor a general introduction to promises.\n\n- [Features](#features)\n- [Quick start](#quick-start)\n- [Synchronous wait](#synchronous-wait)\n- [Cancellation](#cancellation)\n- [API](#api)\n  - [Promise](#promise)\n  - [FulfilledPromise](#fulfilledpromise)\n  - [RejectedPromise](#rejectedpromise)\n- [Promise interop](#promise-interop)\n- [Implementation notes](#implementation-notes)\n\n\n# Features\n\n- [Promises/A+](https://promisesaplus.com/) implementation.\n- Promise resolution and chaining is handled iteratively, allowing for\n  \"infinite\" promise chaining.\n- Promises have a synchronous `wait` method.\n- Promises can be cancelled.\n- Works with any object that has a `then` function.\n- C# style async/await coroutine promises using\n  `GuzzleHttp\\Promise\\Coroutine::of()`.\n\n\n# Quick start\n\nA *promise* represents the eventual result of an asynchronous operation. The\nprimary way of interacting with a promise is through its `then` method, which\nregisters callbacks to receive either a promise's eventual value or the reason\nwhy the promise cannot be fulfilled.\n\n\n## Callbacks\n\nCallbacks are registered with the `then` method by providing an optional \n`$onFulfilled` followed by an optional `$onRejected` function.\n\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise();\n$promise->then(\n    // $onFulfilled\n    function ($value) {\n        echo 'The promise was fulfilled.';\n    },\n    // $onRejected\n    function ($reason) {\n        echo 'The promise was rejected.';\n    }\n);\n```\n\n*Resolving* a promise means that you either fulfill a promise with a *value* or\nreject a promise with a *reason*. Resolving a promises triggers callbacks\nregistered with the promises's `then` method. These callbacks are triggered\nonly once and in the order in which they were added.\n\n\n## Resolving a promise\n\nPromises are fulfilled using the `resolve($value)` method. Resolving a promise\nwith any value other than a `GuzzleHttp\\Promise\\RejectedPromise` will trigger\nall of the onFulfilled callbacks (resolving a promise with a rejected promise\nwill reject the promise and trigger the `$onRejected` callbacks).\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise();\n$promise\n    ->then(function ($value) {\n        // Return a value and don't break the chain\n        return \"Hello, \" . $value;\n    })\n    // This then is executed after the first then and receives the value\n    // returned from the first then.\n    ->then(function ($value) {\n        echo $value;\n    });\n\n// Resolving the promise triggers the $onFulfilled callbacks and outputs\n// \"Hello, reader.\"\n$promise->resolve('reader.');\n```\n\n\n## Promise forwarding\n\nPromises can be chained one after the other. Each then in the chain is a new\npromise. The return value of a promise is what's forwarded to the next\npromise in the chain. Returning a promise in a `then` callback will cause the\nsubsequent promises in the chain to only be fulfilled when the returned promise\nhas been fulfilled. The next promise in the chain will be invoked with the\nresolved value of the promise.\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise();\n$nextPromise = new Promise();\n\n$promise\n    ->then(function ($value) use ($nextPromise) {\n        echo $value;\n        return $nextPromise;\n    })\n    ->then(function ($value) {\n        echo $value;\n    });\n\n// Triggers the first callback and outputs \"A\"\n$promise->resolve('A');\n// Triggers the second callback and outputs \"B\"\n$nextPromise->resolve('B');\n```\n\n## Promise rejection\n\nWhen a promise is rejected, the `$onRejected` callbacks are invoked with the\nrejection reason.\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise();\n$promise->then(null, function ($reason) {\n    echo $reason;\n});\n\n$promise->reject('Error!');\n// Outputs \"Error!\"\n```\n\n## Rejection forwarding\n\nIf an exception is thrown in an `$onRejected` callback, subsequent\n`$onRejected` callbacks are invoked with the thrown exception as the reason.\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise();\n$promise->then(null, function ($reason) {\n    throw new Exception($reason);\n})->then(null, function ($reason) {\n    assert($reason->getMessage() === 'Error!');\n});\n\n$promise->reject('Error!');\n```\n\nYou can also forward a rejection down the promise chain by returning a\n`GuzzleHttp\\Promise\\RejectedPromise` in either an `$onFulfilled` or\n`$onRejected` callback.\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\nuse GuzzleHttp\\Promise\\RejectedPromise;\n\n$promise = new Promise();\n$promise->then(null, function ($reason) {\n    return new RejectedPromise($reason);\n})->then(null, function ($reason) {\n    assert($reason === 'Error!');\n});\n\n$promise->reject('Error!');\n```\n\nIf an exception is not thrown in a `$onRejected` callback and the callback\ndoes not return a rejected promise, downstream `$onFulfilled` callbacks are\ninvoked using the value returned from the `$onRejected` callback.\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise();\n$promise\n    ->then(null, function ($reason) {\n        return \"It's ok\";\n    })\n    ->then(function ($value) {\n        assert($value === \"It's ok\");\n    });\n\n$promise->reject('Error!');\n```\n\n# Synchronous wait\n\nYou can synchronously force promises to complete using a promise's `wait`\nmethod. When creating a promise, you can provide a wait function that is used\nto synchronously force a promise to complete. When a wait function is invoked\nit is expected to deliver a value to the promise or reject the promise. If the\nwait function does not deliver a value, then an exception is thrown. The wait\nfunction provided to a promise constructor is invoked when the `wait` function\nof the promise is called.\n\n```php\n$promise = new Promise(function () use (&$promise) {\n    $promise->resolve('foo');\n});\n\n// Calling wait will return the value of the promise.\necho $promise->wait(); // outputs \"foo\"\n```\n\nIf an exception is encountered while invoking the wait function of a promise,\nthe promise is rejected with the exception and the exception is thrown.\n\n```php\n$promise = new Promise(function () use (&$promise) {\n    throw new Exception('foo');\n});\n\n$promise->wait(); // throws the exception.\n```\n\nCalling `wait` on a promise that has been fulfilled will not trigger the wait\nfunction. It will simply return the previously resolved value.\n\n```php\n$promise = new Promise(function () { die('this is not called!'); });\n$promise->resolve('foo');\necho $promise->wait(); // outputs \"foo\"\n```\n\nCalling `wait` on a promise that has been rejected will throw an exception. If\nthe rejection reason is an instance of `\\Exception` the reason is thrown.\nOtherwise, a `GuzzleHttp\\Promise\\RejectionException` is thrown and the reason\ncan be obtained by calling the `getReason` method of the exception.\n\n```php\n$promise = new Promise();\n$promise->reject('foo');\n$promise->wait();\n```\n\n> PHP Fatal error:  Uncaught exception 'GuzzleHttp\\Promise\\RejectionException' with message 'The promise was rejected with value: foo'\n\n\n## Unwrapping a promise\n\nWhen synchronously waiting on a promise, you are joining the state of the\npromise into the current state of execution (i.e., return the value of the\npromise if it was fulfilled or throw an exception if it was rejected). This is\ncalled \"unwrapping\" the promise. Waiting on a promise will by default unwrap\nthe promise state.\n\nYou can force a promise to resolve and *not* unwrap the state of the promise\nby passing `false` to the first argument of the `wait` function:\n\n```php\n$promise = new Promise();\n$promise->reject('foo');\n// This will not throw an exception. It simply ensures the promise has\n// been resolved.\n$promise->wait(false);\n```\n\nWhen unwrapping a promise, the resolved value of the promise will be waited\nupon until the unwrapped value is not a promise. This means that if you resolve\npromise A with a promise B and unwrap promise A, the value returned by the\nwait function will be the value delivered to promise B.\n\n**Note**: when you do not unwrap the promise, no value is returned.\n\n\n# Cancellation\n\nYou can cancel a promise that has not yet been fulfilled using the `cancel()`\nmethod of a promise. When creating a promise you can provide an optional\ncancel function that when invoked cancels the action of computing a resolution\nof the promise.\n\n\n# API\n\n\n## Promise\n\nWhen creating a promise object, you can provide an optional `$waitFn` and\n`$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is\nexpected to resolve the promise. `$cancelFn` is a function with no arguments\nthat is expected to cancel the computation of a promise. It is invoked when the\n`cancel()` method of a promise is called.\n\n```php\nuse GuzzleHttp\\Promise\\Promise;\n\n$promise = new Promise(\n    function () use (&$promise) {\n        $promise->resolve('waited');\n    },\n    function () {\n        // do something that will cancel the promise computation (e.g., close\n        // a socket, cancel a database query, etc...)\n    }\n);\n\nassert('waited' === $promise->wait());\n```\n\nA promise has the following methods:\n\n- `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`\n  \n  Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.\n\n- `otherwise(callable $onRejected) : PromiseInterface`\n  \n  Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.\n\n- `wait($unwrap = true) : mixed`\n\n  Synchronously waits on the promise to complete.\n  \n  `$unwrap` controls whether or not the value of the promise is returned for a\n  fulfilled promise or if an exception is thrown if the promise is rejected.\n  This is set to `true` by default.\n\n- `cancel()`\n\n  Attempts to cancel the promise if possible. The promise being cancelled and\n  the parent most ancestor that has not yet been resolved will also be\n  cancelled. Any promises waiting on the cancelled promise to resolve will also\n  be cancelled.\n\n- `getState() : string`\n\n  Returns the state of the promise. One of `pending`, `fulfilled`, or\n  `rejected`.\n\n- `resolve($value)`\n\n  Fulfills the promise with the given `$value`.\n\n- `reject($reason)`\n\n  Rejects the promise with the given `$reason`.\n\n\n## FulfilledPromise\n\nA fulfilled promise can be created to represent a promise that has been\nfulfilled.\n\n```php\nuse GuzzleHttp\\Promise\\FulfilledPromise;\n\n$promise = new FulfilledPromise('value');\n\n// Fulfilled callbacks are immediately invoked.\n$promise->then(function ($value) {\n    echo $value;\n});\n```\n\n\n## RejectedPromise\n\nA rejected promise can be created to represent a promise that has been\nrejected.\n\n```php\nuse GuzzleHttp\\Promise\\RejectedPromise;\n\n$promise = new RejectedPromise('Error');\n\n// Rejected callbacks are immediately invoked.\n$promise->then(null, function ($reason) {\n    echo $reason;\n});\n```\n\n\n# Promise interop\n\nThis library works with foreign promises that have a `then` method. This means\nyou can use Guzzle promises with [React promises](https://github.com/reactphp/promise)\nfor example. When a foreign promise is returned inside of a then method\ncallback, promise resolution will occur recursively.\n\n```php\n// Create a React promise\n$deferred = new React\\Promise\\Deferred();\n$reactPromise = $deferred->promise();\n\n// Create a Guzzle promise that is fulfilled with a React promise.\n$guzzlePromise = new GuzzleHttp\\Promise\\Promise();\n$guzzlePromise->then(function ($value) use ($reactPromise) {\n    // Do something something with the value...\n    // Return the React promise\n    return $reactPromise;\n});\n```\n\nPlease note that wait and cancel chaining is no longer possible when forwarding\na foreign promise. You will need to wrap a third-party promise with a Guzzle\npromise in order to utilize wait and cancel functions with foreign promises.\n\n\n## Event Loop Integration\n\nIn order to keep the stack size constant, Guzzle promises are resolved\nasynchronously using a task queue. When waiting on promises synchronously, the\ntask queue will be automatically run to ensure that the blocking promise and\nany forwarded promises are resolved. When using promises asynchronously in an\nevent loop, you will need to run the task queue on each tick of the loop. If\nyou do not run the task queue, then promises will not be resolved.\n\nYou can run the task queue using the `run()` method of the global task queue\ninstance.\n\n```php\n// Get the global task queue\n$queue = GuzzleHttp\\Promise\\Utils::queue();\n$queue->run();\n```\n\nFor example, you could use Guzzle promises with React using a periodic timer:\n\n```php\n$loop = React\\EventLoop\\Factory::create();\n$loop->addPeriodicTimer(0, [$queue, 'run']);\n```\n\n*TODO*: Perhaps adding a `futureTick()` on each tick would be faster?\n\n\n# Implementation notes\n\n\n## Promise resolution and chaining is handled iteratively\n\nBy shuffling pending handlers from one owner to another, promises are\nresolved iteratively, allowing for \"infinite\" then chaining.\n\n```php\n<?php\nrequire 'vendor/autoload.php';\n\nuse GuzzleHttp\\Promise\\Promise;\n\n$parent = new Promise();\n$p = $parent;\n\nfor ($i = 0; $i < 1000; $i++) {\n    $p = $p->then(function ($v) {\n        // The stack size remains constant (a good thing)\n        echo xdebug_get_stack_depth() . ', ';\n        return $v + 1;\n    });\n}\n\n$parent->resolve(0);\nvar_dump($p->wait()); // int(1000)\n\n```\n\nWhen a promise is fulfilled or rejected with a non-promise value, the promise\nthen takes ownership of the handlers of each child promise and delivers values\ndown the chain without using recursion.\n\nWhen a promise is resolved with another promise, the original promise transfers\nall of its pending handlers to the new promise. When the new promise is\neventually resolved, all of the pending handlers are delivered the forwarded\nvalue.\n\n\n## A promise is the deferred.\n\nSome promise libraries implement promises using a deferred object to represent\na computation and a promise object to represent the delivery of the result of\nthe computation. This is a nice separation of computation and delivery because\nconsumers of the promise cannot modify the value that will be eventually\ndelivered.\n\nOne side effect of being able to implement promise resolution and chaining\niteratively is that you need to be able for one promise to reach into the state\nof another promise to shuffle around ownership of handlers. In order to achieve\nthis without making the handlers of a promise publicly mutable, a promise is\nalso the deferred value, allowing promises of the same parent class to reach\ninto and modify the private properties of promises of the same type. While this\ndoes allow consumers of the value to modify the resolution or rejection of the\ndeferred, it is a small price to pay for keeping the stack size constant.\n\n```php\n$promise = new Promise();\n$promise->then(function ($value) { echo $value; });\n// The promise is the deferred value, so you can deliver a value to it.\n$promise->resolve('foo');\n// prints \"foo\"\n```\n\n\n## Upgrading from Function API\n\nA static API was first introduced in 1.4.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API will be removed in 2.0.0. A migration table has been provided here for your convenience:\n\n| Original Function | Replacement Method |\n|----------------|----------------|\n| `queue` | `Utils::queue` |\n| `task` | `Utils::task` |\n| `promise_for` | `Create::promiseFor` |\n| `rejection_for` | `Create::rejectionFor` |\n| `exception_for` | `Create::exceptionFor` |\n| `iter_for` | `Create::iterFor` |\n| `inspect` | `Utils::inspect` |\n| `inspect_all` | `Utils::inspectAll` |\n| `unwrap` | `Utils::unwrap` |\n| `all` | `Utils::all` |\n| `some` | `Utils::some` |\n| `any` | `Utils::any` |\n| `settle` | `Utils::settle` |\n| `each` | `Each::of` |\n| `each_limit` | `Each::ofLimit` |\n| `each_limit_all` | `Each::ofLimitAll` |\n| `!is_fulfilled` | `Is::pending` |\n| `is_fulfilled` | `Is::fulfilled` |\n| `is_rejected` | `Is::rejected` |\n| `is_settled` | `Is::settled` |\n| `coroutine` | `Coroutine::of` |\n\n\n## Security\n\nIf you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/promises/security/policy) for more information.\n\n## License\n\nGuzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.\n\n## For Enterprise\n\nAvailable as part of the Tidelift Subscription\n\nThe maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-promises?utm_source=packagist-guzzlehttp-promises&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/composer.json",
    "content": "{\n    \"name\": \"guzzlehttp/promises\",\n    \"description\": \"Guzzle promises library\",\n    \"keywords\": [\"promise\"],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Graham Campbell\",\n            \"email\": \"hello@gjcampbell.co.uk\",\n            \"homepage\": \"https://github.com/GrahamCampbell\"\n        },\n        {\n            \"name\": \"Michael Dowling\",\n            \"email\": \"mtdowling@gmail.com\",\n            \"homepage\": \"https://github.com/mtdowling\"\n        },\n        {\n            \"name\": \"Tobias Nyholm\",\n            \"email\": \"tobias.nyholm@gmail.com\",\n            \"homepage\": \"https://github.com/Nyholm\"\n        },\n        {\n            \"name\": \"Tobias Schultze\",\n            \"email\": \"webmaster@tubo-world.de\",\n            \"homepage\": \"https://github.com/Tobion\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=5.5\"\n    },\n    \"require-dev\": {\n        \"symfony/phpunit-bridge\": \"^4.4 || ^5.1\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"GuzzleHttp\\\\Promise\\\\\": \"src/\"\n        },\n        \"files\": [\"src/functions_include.php\"]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"GuzzleHttp\\\\Promise\\\\Tests\\\\\": \"tests/\"\n        }\n    },\n    \"scripts\": {\n        \"test\": \"vendor/bin/simple-phpunit\",\n        \"test-ci\": \"vendor/bin/simple-phpunit --coverage-text\"\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.5-dev\"\n        }\n    },\n    \"config\": {\n        \"preferred-install\": \"dist\",\n        \"sort-packages\": true\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/AggregateException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * Exception thrown when too many errors occur in the some() or any() methods.\n */\nclass AggregateException extends RejectionException\n{\n    public function __construct($msg, array $reasons)\n    {\n        parent::__construct(\n            $reasons,\n            sprintf('%s; %d rejected promises', $msg, count($reasons))\n        );\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/CancellationException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * Exception that is set as the reason for a promise that has been cancelled.\n */\nclass CancellationException extends RejectionException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/Coroutine.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\nuse Exception;\nuse Generator;\nuse Throwable;\n\n/**\n * Creates a promise that is resolved using a generator that yields values or\n * promises (somewhat similar to C#'s async keyword).\n *\n * When called, the Coroutine::of method will start an instance of the generator\n * and returns a promise that is fulfilled with its final yielded value.\n *\n * Control is returned back to the generator when the yielded promise settles.\n * This can lead to less verbose code when doing lots of sequential async calls\n * with minimal processing in between.\n *\n *     use GuzzleHttp\\Promise;\n *\n *     function createPromise($value) {\n *         return new Promise\\FulfilledPromise($value);\n *     }\n *\n *     $promise = Promise\\Coroutine::of(function () {\n *         $value = (yield createPromise('a'));\n *         try {\n *             $value = (yield createPromise($value . 'b'));\n *         } catch (\\Exception $e) {\n *             // The promise was rejected.\n *         }\n *         yield $value . 'c';\n *     });\n *\n *     // Outputs \"abc\"\n *     $promise->then(function ($v) { echo $v; });\n *\n * @param callable $generatorFn Generator function to wrap into a promise.\n *\n * @return Promise\n *\n * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration\n */\nfinal class Coroutine implements PromiseInterface\n{\n    /**\n     * @var PromiseInterface|null\n     */\n    private $currentPromise;\n\n    /**\n     * @var Generator\n     */\n    private $generator;\n\n    /**\n     * @var Promise\n     */\n    private $result;\n\n    public function __construct(callable $generatorFn)\n    {\n        $this->generator = $generatorFn();\n        $this->result = new Promise(function () {\n            while (isset($this->currentPromise)) {\n                $this->currentPromise->wait();\n            }\n        });\n        try {\n            $this->nextCoroutine($this->generator->current());\n        } catch (\\Exception $exception) {\n            $this->result->reject($exception);\n        } catch (Throwable $throwable) {\n            $this->result->reject($throwable);\n        }\n    }\n\n    /**\n     * Create a new coroutine.\n     *\n     * @return self\n     */\n    public static function of(callable $generatorFn)\n    {\n        return new self($generatorFn);\n    }\n\n    public function then(\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    ) {\n        return $this->result->then($onFulfilled, $onRejected);\n    }\n\n    public function otherwise(callable $onRejected)\n    {\n        return $this->result->otherwise($onRejected);\n    }\n\n    public function wait($unwrap = true)\n    {\n        return $this->result->wait($unwrap);\n    }\n\n    public function getState()\n    {\n        return $this->result->getState();\n    }\n\n    public function resolve($value)\n    {\n        $this->result->resolve($value);\n    }\n\n    public function reject($reason)\n    {\n        $this->result->reject($reason);\n    }\n\n    public function cancel()\n    {\n        $this->currentPromise->cancel();\n        $this->result->cancel();\n    }\n\n    private function nextCoroutine($yielded)\n    {\n        $this->currentPromise = Create::promiseFor($yielded)\n            ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);\n    }\n\n    /**\n     * @internal\n     */\n    public function _handleSuccess($value)\n    {\n        unset($this->currentPromise);\n        try {\n            $next = $this->generator->send($value);\n            if ($this->generator->valid()) {\n                $this->nextCoroutine($next);\n            } else {\n                $this->result->resolve($value);\n            }\n        } catch (Exception $exception) {\n            $this->result->reject($exception);\n        } catch (Throwable $throwable) {\n            $this->result->reject($throwable);\n        }\n    }\n\n    /**\n     * @internal\n     */\n    public function _handleFailure($reason)\n    {\n        unset($this->currentPromise);\n        try {\n            $nextYield = $this->generator->throw(Create::exceptionFor($reason));\n            // The throw was caught, so keep iterating on the coroutine\n            $this->nextCoroutine($nextYield);\n        } catch (Exception $exception) {\n            $this->result->reject($exception);\n        } catch (Throwable $throwable) {\n            $this->result->reject($throwable);\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/Create.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\nfinal class Create\n{\n    /**\n     * Creates a promise for a value if the value is not a promise.\n     *\n     * @param mixed $value Promise or value.\n     *\n     * @return PromiseInterface\n     */\n    public static function promiseFor($value)\n    {\n        if ($value instanceof PromiseInterface) {\n            return $value;\n        }\n\n        // Return a Guzzle promise that shadows the given promise.\n        if (is_object($value) && method_exists($value, 'then')) {\n            $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;\n            $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;\n            $promise = new Promise($wfn, $cfn);\n            $value->then([$promise, 'resolve'], [$promise, 'reject']);\n            return $promise;\n        }\n\n        return new FulfilledPromise($value);\n    }\n\n    /**\n     * Creates a rejected promise for a reason if the reason is not a promise.\n     * If the provided reason is a promise, then it is returned as-is.\n     *\n     * @param mixed $reason Promise or reason.\n     *\n     * @return PromiseInterface\n     */\n    public static function rejectionFor($reason)\n    {\n        if ($reason instanceof PromiseInterface) {\n            return $reason;\n        }\n\n        return new RejectedPromise($reason);\n    }\n\n    /**\n     * Create an exception for a rejected promise value.\n     *\n     * @param mixed $reason\n     *\n     * @return \\Exception|\\Throwable\n     */\n    public static function exceptionFor($reason)\n    {\n        if ($reason instanceof \\Exception || $reason instanceof \\Throwable) {\n            return $reason;\n        }\n\n        return new RejectionException($reason);\n    }\n\n    /**\n     * Returns an iterator for the given value.\n     *\n     * @param mixed $value\n     *\n     * @return \\Iterator\n     */\n    public static function iterFor($value)\n    {\n        if ($value instanceof \\Iterator) {\n            return $value;\n        }\n\n        if (is_array($value)) {\n            return new \\ArrayIterator($value);\n        }\n\n        return new \\ArrayIterator([$value]);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/Each.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\nfinal class Each\n{\n    /**\n     * Given an iterator that yields promises or values, returns a promise that\n     * is fulfilled with a null value when the iterator has been consumed or\n     * the aggregate promise has been fulfilled or rejected.\n     *\n     * $onFulfilled is a function that accepts the fulfilled value, iterator\n     * index, and the aggregate promise. The callback can invoke any necessary\n     * side effects and choose to resolve or reject the aggregate if needed.\n     *\n     * $onRejected is a function that accepts the rejection reason, iterator\n     * index, and the aggregate promise. The callback can invoke any necessary\n     * side effects and choose to resolve or reject the aggregate if needed.\n     *\n     * @param mixed    $iterable    Iterator or array to iterate over.\n     * @param callable $onFulfilled\n     * @param callable $onRejected\n     *\n     * @return PromiseInterface\n     */\n    public static function of(\n        $iterable,\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    ) {\n        return (new EachPromise($iterable, [\n            'fulfilled' => $onFulfilled,\n            'rejected'  => $onRejected\n        ]))->promise();\n    }\n\n    /**\n     * Like of, but only allows a certain number of outstanding promises at any\n     * given time.\n     *\n     * $concurrency may be an integer or a function that accepts the number of\n     * pending promises and returns a numeric concurrency limit value to allow\n     * for dynamic a concurrency size.\n     *\n     * @param mixed        $iterable\n     * @param int|callable $concurrency\n     * @param callable     $onFulfilled\n     * @param callable     $onRejected\n     *\n     * @return PromiseInterface\n     */\n    public static function ofLimit(\n        $iterable,\n        $concurrency,\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    ) {\n        return (new EachPromise($iterable, [\n            'fulfilled'   => $onFulfilled,\n            'rejected'    => $onRejected,\n            'concurrency' => $concurrency\n        ]))->promise();\n    }\n\n    /**\n     * Like limit, but ensures that no promise in the given $iterable argument\n     * is rejected. If any promise is rejected, then the aggregate promise is\n     * rejected with the encountered rejection.\n     *\n     * @param mixed        $iterable\n     * @param int|callable $concurrency\n     * @param callable     $onFulfilled\n     *\n     * @return PromiseInterface\n     */\n    public static function ofLimitAll(\n        $iterable,\n        $concurrency,\n        callable $onFulfilled = null\n    ) {\n        return each_limit(\n            $iterable,\n            $concurrency,\n            $onFulfilled,\n            function ($reason, $idx, PromiseInterface $aggregate) {\n                $aggregate->reject($reason);\n            }\n        );\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/EachPromise.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * Represents a promise that iterates over many promises and invokes\n * side-effect functions in the process.\n */\nclass EachPromise implements PromisorInterface\n{\n    private $pending = [];\n\n    private $nextPendingIndex = 0;\n\n    /** @var \\Iterator|null */\n    private $iterable;\n\n    /** @var callable|int|null */\n    private $concurrency;\n\n    /** @var callable|null */\n    private $onFulfilled;\n\n    /** @var callable|null */\n    private $onRejected;\n\n    /** @var Promise|null */\n    private $aggregate;\n\n    /** @var bool|null */\n    private $mutex;\n\n    /**\n     * Configuration hash can include the following key value pairs:\n     *\n     * - fulfilled: (callable) Invoked when a promise fulfills. The function\n     *   is invoked with three arguments: the fulfillment value, the index\n     *   position from the iterable list of the promise, and the aggregate\n     *   promise that manages all of the promises. The aggregate promise may\n     *   be resolved from within the callback to short-circuit the promise.\n     * - rejected: (callable) Invoked when a promise is rejected. The\n     *   function is invoked with three arguments: the rejection reason, the\n     *   index position from the iterable list of the promise, and the\n     *   aggregate promise that manages all of the promises. The aggregate\n     *   promise may be resolved from within the callback to short-circuit\n     *   the promise.\n     * - concurrency: (integer) Pass this configuration option to limit the\n     *   allowed number of outstanding concurrently executing promises,\n     *   creating a capped pool of promises. There is no limit by default.\n     *\n     * @param mixed $iterable Promises or values to iterate.\n     * @param array $config   Configuration options\n     */\n    public function __construct($iterable, array $config = [])\n    {\n        $this->iterable = Create::iterFor($iterable);\n\n        if (isset($config['concurrency'])) {\n            $this->concurrency = $config['concurrency'];\n        }\n\n        if (isset($config['fulfilled'])) {\n            $this->onFulfilled = $config['fulfilled'];\n        }\n\n        if (isset($config['rejected'])) {\n            $this->onRejected = $config['rejected'];\n        }\n    }\n\n    /** @psalm-suppress InvalidNullableReturnType */\n    public function promise()\n    {\n        if ($this->aggregate) {\n            return $this->aggregate;\n        }\n\n        try {\n            $this->createPromise();\n            /** @psalm-assert Promise $this->aggregate */\n            $this->iterable->rewind();\n            $this->refillPending();\n        } catch (\\Throwable $e) {\n            /**\n             * @psalm-suppress NullReference\n             * @phpstan-ignore-next-line\n             */\n            $this->aggregate->reject($e);\n        } catch (\\Exception $e) {\n            /**\n             * @psalm-suppress NullReference\n             * @phpstan-ignore-next-line\n             */\n            $this->aggregate->reject($e);\n        }\n\n        /**\n         * @psalm-suppress NullableReturnStatement\n         * @phpstan-ignore-next-line\n         */\n        return $this->aggregate;\n    }\n\n    private function createPromise()\n    {\n        $this->mutex = false;\n        $this->aggregate = new Promise(function () {\n            if ($this->checkIfFinished()) {\n                return;\n            }\n            reset($this->pending);\n            // Consume a potentially fluctuating list of promises while\n            // ensuring that indexes are maintained (precluding array_shift).\n            while ($promise = current($this->pending)) {\n                next($this->pending);\n                $promise->wait();\n                if (Is::settled($this->aggregate)) {\n                    return;\n                }\n            }\n        });\n\n        // Clear the references when the promise is resolved.\n        $clearFn = function () {\n            $this->iterable = $this->concurrency = $this->pending = null;\n            $this->onFulfilled = $this->onRejected = null;\n            $this->nextPendingIndex = 0;\n        };\n\n        $this->aggregate->then($clearFn, $clearFn);\n    }\n\n    private function refillPending()\n    {\n        if (!$this->concurrency) {\n            // Add all pending promises.\n            while ($this->addPending() && $this->advanceIterator());\n            return;\n        }\n\n        // Add only up to N pending promises.\n        $concurrency = is_callable($this->concurrency)\n            ? call_user_func($this->concurrency, count($this->pending))\n            : $this->concurrency;\n        $concurrency = max($concurrency - count($this->pending), 0);\n        // Concurrency may be set to 0 to disallow new promises.\n        if (!$concurrency) {\n            return;\n        }\n        // Add the first pending promise.\n        $this->addPending();\n        // Note this is special handling for concurrency=1 so that we do\n        // not advance the iterator after adding the first promise. This\n        // helps work around issues with generators that might not have the\n        // next value to yield until promise callbacks are called.\n        while (--$concurrency\n            && $this->advanceIterator()\n            && $this->addPending());\n    }\n\n    private function addPending()\n    {\n        if (!$this->iterable || !$this->iterable->valid()) {\n            return false;\n        }\n\n        $promise = Create::promiseFor($this->iterable->current());\n        $key = $this->iterable->key();\n\n        // Iterable keys may not be unique, so we use a counter to\n        // guarantee uniqueness\n        $idx = $this->nextPendingIndex++;\n\n        $this->pending[$idx] = $promise->then(\n            function ($value) use ($idx, $key) {\n                if ($this->onFulfilled) {\n                    call_user_func(\n                        $this->onFulfilled,\n                        $value,\n                        $key,\n                        $this->aggregate\n                    );\n                }\n                $this->step($idx);\n            },\n            function ($reason) use ($idx, $key) {\n                if ($this->onRejected) {\n                    call_user_func(\n                        $this->onRejected,\n                        $reason,\n                        $key,\n                        $this->aggregate\n                    );\n                }\n                $this->step($idx);\n            }\n        );\n\n        return true;\n    }\n\n    private function advanceIterator()\n    {\n        // Place a lock on the iterator so that we ensure to not recurse,\n        // preventing fatal generator errors.\n        if ($this->mutex) {\n            return false;\n        }\n\n        $this->mutex = true;\n\n        try {\n            $this->iterable->next();\n            $this->mutex = false;\n            return true;\n        } catch (\\Throwable $e) {\n            $this->aggregate->reject($e);\n            $this->mutex = false;\n            return false;\n        } catch (\\Exception $e) {\n            $this->aggregate->reject($e);\n            $this->mutex = false;\n            return false;\n        }\n    }\n\n    private function step($idx)\n    {\n        // If the promise was already resolved, then ignore this step.\n        if (Is::settled($this->aggregate)) {\n            return;\n        }\n\n        unset($this->pending[$idx]);\n\n        // Only refill pending promises if we are not locked, preventing the\n        // EachPromise to recursively invoke the provided iterator, which\n        // cause a fatal error: \"Cannot resume an already running generator\"\n        if ($this->advanceIterator() && !$this->checkIfFinished()) {\n            // Add more pending promises if possible.\n            $this->refillPending();\n        }\n    }\n\n    private function checkIfFinished()\n    {\n        if (!$this->pending && !$this->iterable->valid()) {\n            // Resolve the promise if there's nothing left to do.\n            $this->aggregate->resolve(null);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/FulfilledPromise.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * A promise that has been fulfilled.\n *\n * Thenning off of this promise will invoke the onFulfilled callback\n * immediately and ignore other callbacks.\n */\nclass FulfilledPromise implements PromiseInterface\n{\n    private $value;\n\n    public function __construct($value)\n    {\n        if (is_object($value) && method_exists($value, 'then')) {\n            throw new \\InvalidArgumentException(\n                'You cannot create a FulfilledPromise with a promise.'\n            );\n        }\n\n        $this->value = $value;\n    }\n\n    public function then(\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    ) {\n        // Return itself if there is no onFulfilled function.\n        if (!$onFulfilled) {\n            return $this;\n        }\n\n        $queue = Utils::queue();\n        $p = new Promise([$queue, 'run']);\n        $value = $this->value;\n        $queue->add(static function () use ($p, $value, $onFulfilled) {\n            if (Is::pending($p)) {\n                try {\n                    $p->resolve($onFulfilled($value));\n                } catch (\\Throwable $e) {\n                    $p->reject($e);\n                } catch (\\Exception $e) {\n                    $p->reject($e);\n                }\n            }\n        });\n\n        return $p;\n    }\n\n    public function otherwise(callable $onRejected)\n    {\n        return $this->then(null, $onRejected);\n    }\n\n    public function wait($unwrap = true, $defaultDelivery = null)\n    {\n        return $unwrap ? $this->value : null;\n    }\n\n    public function getState()\n    {\n        return self::FULFILLED;\n    }\n\n    public function resolve($value)\n    {\n        if ($value !== $this->value) {\n            throw new \\LogicException(\"Cannot resolve a fulfilled promise\");\n        }\n    }\n\n    public function reject($reason)\n    {\n        throw new \\LogicException(\"Cannot reject a fulfilled promise\");\n    }\n\n    public function cancel()\n    {\n        // pass\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/Is.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\nfinal class Is\n{\n    /**\n     * Returns true if a promise is pending.\n     *\n     * @return bool\n     */\n    public static function pending(PromiseInterface $promise)\n    {\n        return $promise->getState() === PromiseInterface::PENDING;\n    }\n\n    /**\n     * Returns true if a promise is fulfilled or rejected.\n     *\n     * @return bool\n     */\n    public static function settled(PromiseInterface $promise)\n    {\n        return $promise->getState() !== PromiseInterface::PENDING;\n    }\n\n    /**\n     * Returns true if a promise is fulfilled.\n     *\n     * @return bool\n     */\n    public static function fulfilled(PromiseInterface $promise)\n    {\n        return $promise->getState() === PromiseInterface::FULFILLED;\n    }\n\n    /**\n     * Returns true if a promise is rejected.\n     *\n     * @return bool\n     */\n    public static function rejected(PromiseInterface $promise)\n    {\n        return $promise->getState() === PromiseInterface::REJECTED;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/Promise.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * Promises/A+ implementation that avoids recursion when possible.\n *\n * @link https://promisesaplus.com/\n */\nclass Promise implements PromiseInterface\n{\n    private $state = self::PENDING;\n    private $result;\n    private $cancelFn;\n    private $waitFn;\n    private $waitList;\n    private $handlers = [];\n\n    /**\n     * @param callable $waitFn   Fn that when invoked resolves the promise.\n     * @param callable $cancelFn Fn that when invoked cancels the promise.\n     */\n    public function __construct(\n        callable $waitFn = null,\n        callable $cancelFn = null\n    ) {\n        $this->waitFn = $waitFn;\n        $this->cancelFn = $cancelFn;\n    }\n\n    public function then(\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    ) {\n        if ($this->state === self::PENDING) {\n            $p = new Promise(null, [$this, 'cancel']);\n            $this->handlers[] = [$p, $onFulfilled, $onRejected];\n            $p->waitList = $this->waitList;\n            $p->waitList[] = $this;\n            return $p;\n        }\n\n        // Return a fulfilled promise and immediately invoke any callbacks.\n        if ($this->state === self::FULFILLED) {\n            $promise = Create::promiseFor($this->result);\n            return $onFulfilled ? $promise->then($onFulfilled) : $promise;\n        }\n\n        // It's either cancelled or rejected, so return a rejected promise\n        // and immediately invoke any callbacks.\n        $rejection = Create::rejectionFor($this->result);\n        return $onRejected ? $rejection->then(null, $onRejected) : $rejection;\n    }\n\n    public function otherwise(callable $onRejected)\n    {\n        return $this->then(null, $onRejected);\n    }\n\n    public function wait($unwrap = true)\n    {\n        $this->waitIfPending();\n\n        if ($this->result instanceof PromiseInterface) {\n            return $this->result->wait($unwrap);\n        }\n        if ($unwrap) {\n            if ($this->state === self::FULFILLED) {\n                return $this->result;\n            }\n            // It's rejected so \"unwrap\" and throw an exception.\n            throw Create::exceptionFor($this->result);\n        }\n    }\n\n    public function getState()\n    {\n        return $this->state;\n    }\n\n    public function cancel()\n    {\n        if ($this->state !== self::PENDING) {\n            return;\n        }\n\n        $this->waitFn = $this->waitList = null;\n\n        if ($this->cancelFn) {\n            $fn = $this->cancelFn;\n            $this->cancelFn = null;\n            try {\n                $fn();\n            } catch (\\Throwable $e) {\n                $this->reject($e);\n            } catch (\\Exception $e) {\n                $this->reject($e);\n            }\n        }\n\n        // Reject the promise only if it wasn't rejected in a then callback.\n        /** @psalm-suppress RedundantCondition */\n        if ($this->state === self::PENDING) {\n            $this->reject(new CancellationException('Promise has been cancelled'));\n        }\n    }\n\n    public function resolve($value)\n    {\n        $this->settle(self::FULFILLED, $value);\n    }\n\n    public function reject($reason)\n    {\n        $this->settle(self::REJECTED, $reason);\n    }\n\n    private function settle($state, $value)\n    {\n        if ($this->state !== self::PENDING) {\n            // Ignore calls with the same resolution.\n            if ($state === $this->state && $value === $this->result) {\n                return;\n            }\n            throw $this->state === $state\n                ? new \\LogicException(\"The promise is already {$state}.\")\n                : new \\LogicException(\"Cannot change a {$this->state} promise to {$state}\");\n        }\n\n        if ($value === $this) {\n            throw new \\LogicException('Cannot fulfill or reject a promise with itself');\n        }\n\n        // Clear out the state of the promise but stash the handlers.\n        $this->state = $state;\n        $this->result = $value;\n        $handlers = $this->handlers;\n        $this->handlers = null;\n        $this->waitList = $this->waitFn = null;\n        $this->cancelFn = null;\n\n        if (!$handlers) {\n            return;\n        }\n\n        // If the value was not a settled promise or a thenable, then resolve\n        // it in the task queue using the correct ID.\n        if (!is_object($value) || !method_exists($value, 'then')) {\n            $id = $state === self::FULFILLED ? 1 : 2;\n            // It's a success, so resolve the handlers in the queue.\n            Utils::queue()->add(static function () use ($id, $value, $handlers) {\n                foreach ($handlers as $handler) {\n                    self::callHandler($id, $value, $handler);\n                }\n            });\n        } elseif ($value instanceof Promise && Is::pending($value)) {\n            // We can just merge our handlers onto the next promise.\n            $value->handlers = array_merge($value->handlers, $handlers);\n        } else {\n            // Resolve the handlers when the forwarded promise is resolved.\n            $value->then(\n                static function ($value) use ($handlers) {\n                    foreach ($handlers as $handler) {\n                        self::callHandler(1, $value, $handler);\n                    }\n                },\n                static function ($reason) use ($handlers) {\n                    foreach ($handlers as $handler) {\n                        self::callHandler(2, $reason, $handler);\n                    }\n                }\n            );\n        }\n    }\n\n    /**\n     * Call a stack of handlers using a specific callback index and value.\n     *\n     * @param int   $index   1 (resolve) or 2 (reject).\n     * @param mixed $value   Value to pass to the callback.\n     * @param array $handler Array of handler data (promise and callbacks).\n     */\n    private static function callHandler($index, $value, array $handler)\n    {\n        /** @var PromiseInterface $promise */\n        $promise = $handler[0];\n\n        // The promise may have been cancelled or resolved before placing\n        // this thunk in the queue.\n        if (Is::settled($promise)) {\n            return;\n        }\n\n        try {\n            if (isset($handler[$index])) {\n                /*\n                 * If $f throws an exception, then $handler will be in the exception\n                 * stack trace. Since $handler contains a reference to the callable\n                 * itself we get a circular reference. We clear the $handler\n                 * here to avoid that memory leak.\n                 */\n                $f = $handler[$index];\n                unset($handler);\n                $promise->resolve($f($value));\n            } elseif ($index === 1) {\n                // Forward resolution values as-is.\n                $promise->resolve($value);\n            } else {\n                // Forward rejections down the chain.\n                $promise->reject($value);\n            }\n        } catch (\\Throwable $reason) {\n            $promise->reject($reason);\n        } catch (\\Exception $reason) {\n            $promise->reject($reason);\n        }\n    }\n\n    private function waitIfPending()\n    {\n        if ($this->state !== self::PENDING) {\n            return;\n        } elseif ($this->waitFn) {\n            $this->invokeWaitFn();\n        } elseif ($this->waitList) {\n            $this->invokeWaitList();\n        } else {\n            // If there's no wait function, then reject the promise.\n            $this->reject('Cannot wait on a promise that has '\n                . 'no internal wait function. You must provide a wait '\n                . 'function when constructing the promise to be able to '\n                . 'wait on a promise.');\n        }\n\n        Utils::queue()->run();\n\n        /** @psalm-suppress RedundantCondition */\n        if ($this->state === self::PENDING) {\n            $this->reject('Invoking the wait callback did not resolve the promise');\n        }\n    }\n\n    private function invokeWaitFn()\n    {\n        try {\n            $wfn = $this->waitFn;\n            $this->waitFn = null;\n            $wfn(true);\n        } catch (\\Exception $reason) {\n            if ($this->state === self::PENDING) {\n                // The promise has not been resolved yet, so reject the promise\n                // with the exception.\n                $this->reject($reason);\n            } else {\n                // The promise was already resolved, so there's a problem in\n                // the application.\n                throw $reason;\n            }\n        }\n    }\n\n    private function invokeWaitList()\n    {\n        $waitList = $this->waitList;\n        $this->waitList = null;\n\n        foreach ($waitList as $result) {\n            do {\n                $result->waitIfPending();\n                $result = $result->result;\n            } while ($result instanceof Promise);\n\n            if ($result instanceof PromiseInterface) {\n                $result->wait(false);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/PromiseInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * A promise represents the eventual result of an asynchronous operation.\n *\n * The primary way of interacting with a promise is through its then method,\n * which registers callbacks to receive either a promise’s eventual value or\n * the reason why the promise cannot be fulfilled.\n *\n * @link https://promisesaplus.com/\n */\ninterface PromiseInterface\n{\n    const PENDING = 'pending';\n    const FULFILLED = 'fulfilled';\n    const REJECTED = 'rejected';\n\n    /**\n     * Appends fulfillment and rejection handlers to the promise, and returns\n     * a new promise resolving to the return value of the called handler.\n     *\n     * @param callable $onFulfilled Invoked when the promise fulfills.\n     * @param callable $onRejected  Invoked when the promise is rejected.\n     *\n     * @return PromiseInterface\n     */\n    public function then(\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    );\n\n    /**\n     * Appends a rejection handler callback to the promise, and returns a new\n     * promise resolving to the return value of the callback if it is called,\n     * or to its original fulfillment value if the promise is instead\n     * fulfilled.\n     *\n     * @param callable $onRejected Invoked when the promise is rejected.\n     *\n     * @return PromiseInterface\n     */\n    public function otherwise(callable $onRejected);\n\n    /**\n     * Get the state of the promise (\"pending\", \"rejected\", or \"fulfilled\").\n     *\n     * The three states can be checked against the constants defined on\n     * PromiseInterface: PENDING, FULFILLED, and REJECTED.\n     *\n     * @return string\n     */\n    public function getState();\n\n    /**\n     * Resolve the promise with the given value.\n     *\n     * @param mixed $value\n     *\n     * @throws \\RuntimeException if the promise is already resolved.\n     */\n    public function resolve($value);\n\n    /**\n     * Reject the promise with the given reason.\n     *\n     * @param mixed $reason\n     *\n     * @throws \\RuntimeException if the promise is already resolved.\n     */\n    public function reject($reason);\n\n    /**\n     * Cancels the promise if possible.\n     *\n     * @link https://github.com/promises-aplus/cancellation-spec/issues/7\n     */\n    public function cancel();\n\n    /**\n     * Waits until the promise completes if possible.\n     *\n     * Pass $unwrap as true to unwrap the result of the promise, either\n     * returning the resolved value or throwing the rejected exception.\n     *\n     * If the promise cannot be waited on, then the promise will be rejected.\n     *\n     * @param bool $unwrap\n     *\n     * @return mixed\n     *\n     * @throws \\LogicException if the promise has no wait function or if the\n     *                         promise does not settle after waiting.\n     */\n    public function wait($unwrap = true);\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/PromisorInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * Interface used with classes that return a promise.\n */\ninterface PromisorInterface\n{\n    /**\n     * Returns a promise.\n     *\n     * @return PromiseInterface\n     */\n    public function promise();\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/RejectedPromise.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * A promise that has been rejected.\n *\n * Thenning off of this promise will invoke the onRejected callback\n * immediately and ignore other callbacks.\n */\nclass RejectedPromise implements PromiseInterface\n{\n    private $reason;\n\n    public function __construct($reason)\n    {\n        if (is_object($reason) && method_exists($reason, 'then')) {\n            throw new \\InvalidArgumentException(\n                'You cannot create a RejectedPromise with a promise.'\n            );\n        }\n\n        $this->reason = $reason;\n    }\n\n    public function then(\n        callable $onFulfilled = null,\n        callable $onRejected = null\n    ) {\n        // If there's no onRejected callback then just return self.\n        if (!$onRejected) {\n            return $this;\n        }\n\n        $queue = Utils::queue();\n        $reason = $this->reason;\n        $p = new Promise([$queue, 'run']);\n        $queue->add(static function () use ($p, $reason, $onRejected) {\n            if (Is::pending($p)) {\n                try {\n                    // Return a resolved promise if onRejected does not throw.\n                    $p->resolve($onRejected($reason));\n                } catch (\\Throwable $e) {\n                    // onRejected threw, so return a rejected promise.\n                    $p->reject($e);\n                } catch (\\Exception $e) {\n                    // onRejected threw, so return a rejected promise.\n                    $p->reject($e);\n                }\n            }\n        });\n\n        return $p;\n    }\n\n    public function otherwise(callable $onRejected)\n    {\n        return $this->then(null, $onRejected);\n    }\n\n    public function wait($unwrap = true, $defaultDelivery = null)\n    {\n        if ($unwrap) {\n            throw Create::exceptionFor($this->reason);\n        }\n\n        return null;\n    }\n\n    public function getState()\n    {\n        return self::REJECTED;\n    }\n\n    public function resolve($value)\n    {\n        throw new \\LogicException(\"Cannot resolve a rejected promise\");\n    }\n\n    public function reject($reason)\n    {\n        if ($reason !== $this->reason) {\n            throw new \\LogicException(\"Cannot reject a rejected promise\");\n        }\n    }\n\n    public function cancel()\n    {\n        // pass\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/RejectionException.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * A special exception that is thrown when waiting on a rejected promise.\n *\n * The reason value is available via the getReason() method.\n */\nclass RejectionException extends \\RuntimeException\n{\n    /** @var mixed Rejection reason. */\n    private $reason;\n\n    /**\n     * @param mixed  $reason      Rejection reason.\n     * @param string $description Optional description\n     */\n    public function __construct($reason, $description = null)\n    {\n        $this->reason = $reason;\n\n        $message = 'The promise was rejected';\n\n        if ($description) {\n            $message .= ' with reason: ' . $description;\n        } elseif (is_string($reason)\n            || (is_object($reason) && method_exists($reason, '__toString'))\n        ) {\n            $message .= ' with reason: ' . $this->reason;\n        } elseif ($reason instanceof \\JsonSerializable) {\n            $message .= ' with reason: '\n                . json_encode($this->reason, JSON_PRETTY_PRINT);\n        }\n\n        parent::__construct($message);\n    }\n\n    /**\n     * Returns the rejection reason.\n     *\n     * @return mixed\n     */\n    public function getReason()\n    {\n        return $this->reason;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/TaskQueue.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * A task queue that executes tasks in a FIFO order.\n *\n * This task queue class is used to settle promises asynchronously and\n * maintains a constant stack size. You can use the task queue asynchronously\n * by calling the `run()` function of the global task queue in an event loop.\n *\n *     GuzzleHttp\\Promise\\Utils::queue()->run();\n */\nclass TaskQueue implements TaskQueueInterface\n{\n    private $enableShutdown = true;\n    private $queue = [];\n\n    public function __construct($withShutdown = true)\n    {\n        if ($withShutdown) {\n            register_shutdown_function(function () {\n                if ($this->enableShutdown) {\n                    // Only run the tasks if an E_ERROR didn't occur.\n                    $err = error_get_last();\n                    if (!$err || ($err['type'] ^ E_ERROR)) {\n                        $this->run();\n                    }\n                }\n            });\n        }\n    }\n\n    public function isEmpty()\n    {\n        return !$this->queue;\n    }\n\n    public function add(callable $task)\n    {\n        $this->queue[] = $task;\n    }\n\n    public function run()\n    {\n        while ($task = array_shift($this->queue)) {\n            /** @var callable $task */\n            $task();\n        }\n    }\n\n    /**\n     * The task queue will be run and exhausted by default when the process\n     * exits IFF the exit is not the result of a PHP E_ERROR error.\n     *\n     * You can disable running the automatic shutdown of the queue by calling\n     * this function. If you disable the task queue shutdown process, then you\n     * MUST either run the task queue (as a result of running your event loop\n     * or manually using the run() method) or wait on each outstanding promise.\n     *\n     * Note: This shutdown will occur before any destructors are triggered.\n     */\n    public function disableShutdown()\n    {\n        $this->enableShutdown = false;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/TaskQueueInterface.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\ninterface TaskQueueInterface\n{\n    /**\n     * Returns true if the queue is empty.\n     *\n     * @return bool\n     */\n    public function isEmpty();\n\n    /**\n     * Adds a task to the queue that will be executed the next time run is\n     * called.\n     */\n    public function add(callable $task);\n\n    /**\n     * Execute all of the pending task in the queue.\n     */\n    public function run();\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/Utils.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\nfinal class Utils\n{\n    /**\n     * Get the global task queue used for promise resolution.\n     *\n     * This task queue MUST be run in an event loop in order for promises to be\n     * settled asynchronously. It will be automatically run when synchronously\n     * waiting on a promise.\n     *\n     * <code>\n     * while ($eventLoop->isRunning()) {\n     *     GuzzleHttp\\Promise\\Utils::queue()->run();\n     * }\n     * </code>\n     *\n     * @param TaskQueueInterface $assign Optionally specify a new queue instance.\n     *\n     * @return TaskQueueInterface\n     */\n    public static function queue(TaskQueueInterface $assign = null)\n    {\n        static $queue;\n\n        if ($assign) {\n            $queue = $assign;\n        } elseif (!$queue) {\n            $queue = new TaskQueue();\n        }\n\n        return $queue;\n    }\n\n    /**\n     * Adds a function to run in the task queue when it is next `run()` and\n     * returns a promise that is fulfilled or rejected with the result.\n     *\n     * @param callable $task Task function to run.\n     *\n     * @return PromiseInterface\n     */\n    public static function task(callable $task)\n    {\n        $queue = self::queue();\n        $promise = new Promise([$queue, 'run']);\n        $queue->add(function () use ($task, $promise) {\n            try {\n                if (Is::pending($promise)) {\n                    $promise->resolve($task());\n                }\n            } catch (\\Throwable $e) {\n                $promise->reject($e);\n            } catch (\\Exception $e) {\n                $promise->reject($e);\n            }\n        });\n\n        return $promise;\n    }\n\n    /**\n     * Synchronously waits on a promise to resolve and returns an inspection\n     * state array.\n     *\n     * Returns a state associative array containing a \"state\" key mapping to a\n     * valid promise state. If the state of the promise is \"fulfilled\", the\n     * array will contain a \"value\" key mapping to the fulfilled value of the\n     * promise. If the promise is rejected, the array will contain a \"reason\"\n     * key mapping to the rejection reason of the promise.\n     *\n     * @param PromiseInterface $promise Promise or value.\n     *\n     * @return array\n     */\n    public static function inspect(PromiseInterface $promise)\n    {\n        try {\n            return [\n                'state' => PromiseInterface::FULFILLED,\n                'value' => $promise->wait()\n            ];\n        } catch (RejectionException $e) {\n            return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];\n        } catch (\\Throwable $e) {\n            return ['state' => PromiseInterface::REJECTED, 'reason' => $e];\n        } catch (\\Exception $e) {\n            return ['state' => PromiseInterface::REJECTED, 'reason' => $e];\n        }\n    }\n\n    /**\n     * Waits on all of the provided promises, but does not unwrap rejected\n     * promises as thrown exception.\n     *\n     * Returns an array of inspection state arrays.\n     *\n     * @see inspect for the inspection state array format.\n     *\n     * @param PromiseInterface[] $promises Traversable of promises to wait upon.\n     *\n     * @return array\n     */\n    public static function inspectAll($promises)\n    {\n        $results = [];\n        foreach ($promises as $key => $promise) {\n            $results[$key] = inspect($promise);\n        }\n\n        return $results;\n    }\n\n    /**\n     * Waits on all of the provided promises and returns the fulfilled values.\n     *\n     * Returns an array that contains the value of each promise (in the same\n     * order the promises were provided). An exception is thrown if any of the\n     * promises are rejected.\n     *\n     * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.\n     *\n     * @return array\n     *\n     * @throws \\Exception on error\n     * @throws \\Throwable on error in PHP >=7\n     */\n    public static function unwrap($promises)\n    {\n        $results = [];\n        foreach ($promises as $key => $promise) {\n            $results[$key] = $promise->wait();\n        }\n\n        return $results;\n    }\n\n    /**\n     * Given an array of promises, return a promise that is fulfilled when all\n     * the items in the array are fulfilled.\n     *\n     * The promise's fulfillment value is an array with fulfillment values at\n     * respective positions to the original array. If any promise in the array\n     * rejects, the returned promise is rejected with the rejection reason.\n     *\n     * @param mixed $promises  Promises or values.\n     * @param bool  $recursive If true, resolves new promises that might have been added to the stack during its own resolution.\n     *\n     * @return PromiseInterface\n     */\n    public static function all($promises, $recursive = false)\n    {\n        $results = [];\n        $promise = Each::of(\n            $promises,\n            function ($value, $idx) use (&$results) {\n                $results[$idx] = $value;\n            },\n            function ($reason, $idx, Promise $aggregate) {\n                $aggregate->reject($reason);\n            }\n        )->then(function () use (&$results) {\n            ksort($results);\n            return $results;\n        });\n\n        if (true === $recursive) {\n            $promise = $promise->then(function ($results) use ($recursive, &$promises) {\n                foreach ($promises as $promise) {\n                    if (Is::pending($promise)) {\n                        return self::all($promises, $recursive);\n                    }\n                }\n                return $results;\n            });\n        }\n\n        return $promise;\n    }\n\n    /**\n     * Initiate a competitive race between multiple promises or values (values\n     * will become immediately fulfilled promises).\n     *\n     * When count amount of promises have been fulfilled, the returned promise\n     * is fulfilled with an array that contains the fulfillment values of the\n     * winners in order of resolution.\n     *\n     * This promise is rejected with a {@see AggregateException} if the number\n     * of fulfilled promises is less than the desired $count.\n     *\n     * @param int   $count    Total number of promises.\n     * @param mixed $promises Promises or values.\n     *\n     * @return PromiseInterface\n     */\n    public static function some($count, $promises)\n    {\n        $results = [];\n        $rejections = [];\n\n        return Each::of(\n            $promises,\n            function ($value, $idx, PromiseInterface $p) use (&$results, $count) {\n                if (Is::settled($p)) {\n                    return;\n                }\n                $results[$idx] = $value;\n                if (count($results) >= $count) {\n                    $p->resolve(null);\n                }\n            },\n            function ($reason) use (&$rejections) {\n                $rejections[] = $reason;\n            }\n        )->then(\n            function () use (&$results, &$rejections, $count) {\n                if (count($results) !== $count) {\n                    throw new AggregateException(\n                        'Not enough promises to fulfill count',\n                        $rejections\n                    );\n                }\n                ksort($results);\n                return array_values($results);\n            }\n        );\n    }\n\n    /**\n     * Like some(), with 1 as count. However, if the promise fulfills, the\n     * fulfillment value is not an array of 1 but the value directly.\n     *\n     * @param mixed $promises Promises or values.\n     *\n     * @return PromiseInterface\n     */\n    public static function any($promises)\n    {\n        return self::some(1, $promises)->then(function ($values) {\n            return $values[0];\n        });\n    }\n\n    /**\n     * Returns a promise that is fulfilled when all of the provided promises have\n     * been fulfilled or rejected.\n     *\n     * The returned promise is fulfilled with an array of inspection state arrays.\n     *\n     * @see inspect for the inspection state array format.\n     *\n     * @param mixed $promises Promises or values.\n     *\n     * @return PromiseInterface\n     */\n    public static function settle($promises)\n    {\n        $results = [];\n\n        return Each::of(\n            $promises,\n            function ($value, $idx) use (&$results) {\n                $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];\n            },\n            function ($reason, $idx) use (&$results) {\n                $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];\n            }\n        )->then(function () use (&$results) {\n            ksort($results);\n            return $results;\n        });\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/functions.php",
    "content": "<?php\n\nnamespace GuzzleHttp\\Promise;\n\n/**\n * Get the global task queue used for promise resolution.\n *\n * This task queue MUST be run in an event loop in order for promises to be\n * settled asynchronously. It will be automatically run when synchronously\n * waiting on a promise.\n *\n * <code>\n * while ($eventLoop->isRunning()) {\n *     GuzzleHttp\\Promise\\queue()->run();\n * }\n * </code>\n *\n * @param TaskQueueInterface $assign Optionally specify a new queue instance.\n *\n * @return TaskQueueInterface\n *\n * @deprecated queue will be removed in guzzlehttp/promises:2.0. Use Utils::queue instead.\n */\nfunction queue(TaskQueueInterface $assign = null)\n{\n    return Utils::queue($assign);\n}\n\n/**\n * Adds a function to run in the task queue when it is next `run()` and returns\n * a promise that is fulfilled or rejected with the result.\n *\n * @param callable $task Task function to run.\n *\n * @return PromiseInterface\n *\n * @deprecated task will be removed in guzzlehttp/promises:2.0. Use Utils::task instead.\n */\nfunction task(callable $task)\n{\n    return Utils::task($task);\n}\n\n/**\n * Creates a promise for a value if the value is not a promise.\n *\n * @param mixed $value Promise or value.\n *\n * @return PromiseInterface\n *\n * @deprecated promise_for will be removed in guzzlehttp/promises:2.0. Use Create::promiseFor instead.\n */\nfunction promise_for($value)\n{\n    return Create::promiseFor($value);\n}\n\n/**\n * Creates a rejected promise for a reason if the reason is not a promise. If\n * the provided reason is a promise, then it is returned as-is.\n *\n * @param mixed $reason Promise or reason.\n *\n * @return PromiseInterface\n *\n * @deprecated rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead.\n */\nfunction rejection_for($reason)\n{\n    return Create::rejectionFor($reason);\n}\n\n/**\n * Create an exception for a rejected promise value.\n *\n * @param mixed $reason\n *\n * @return \\Exception|\\Throwable\n *\n * @deprecated exception_for will be removed in guzzlehttp/promises:2.0. Use Create::exceptionFor instead.\n */\nfunction exception_for($reason)\n{\n    return Create::exceptionFor($reason);\n}\n\n/**\n * Returns an iterator for the given value.\n *\n * @param mixed $value\n *\n * @return \\Iterator\n *\n * @deprecated iter_for will be removed in guzzlehttp/promises:2.0. Use Create::iterFor instead.\n */\nfunction iter_for($value)\n{\n    return Create::iterFor($value);\n}\n\n/**\n * Synchronously waits on a promise to resolve and returns an inspection state\n * array.\n *\n * Returns a state associative array containing a \"state\" key mapping to a\n * valid promise state. If the state of the promise is \"fulfilled\", the array\n * will contain a \"value\" key mapping to the fulfilled value of the promise. If\n * the promise is rejected, the array will contain a \"reason\" key mapping to\n * the rejection reason of the promise.\n *\n * @param PromiseInterface $promise Promise or value.\n *\n * @return array\n *\n * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspect instead.\n */\nfunction inspect(PromiseInterface $promise)\n{\n    return Utils::inspect($promise);\n}\n\n/**\n * Waits on all of the provided promises, but does not unwrap rejected promises\n * as thrown exception.\n *\n * Returns an array of inspection state arrays.\n *\n * @see inspect for the inspection state array format.\n *\n * @param PromiseInterface[] $promises Traversable of promises to wait upon.\n *\n * @return array\n *\n * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspectAll instead.\n */\nfunction inspect_all($promises)\n{\n    return Utils::inspectAll($promises);\n}\n\n/**\n * Waits on all of the provided promises and returns the fulfilled values.\n *\n * Returns an array that contains the value of each promise (in the same order\n * the promises were provided). An exception is thrown if any of the promises\n * are rejected.\n *\n * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.\n *\n * @return array\n *\n * @throws \\Exception on error\n * @throws \\Throwable on error in PHP >=7\n *\n * @deprecated unwrap will be removed in guzzlehttp/promises:2.0. Use Utils::unwrap instead.\n */\nfunction unwrap($promises)\n{\n    return Utils::unwrap($promises);\n}\n\n/**\n * Given an array of promises, return a promise that is fulfilled when all the\n * items in the array are fulfilled.\n *\n * The promise's fulfillment value is an array with fulfillment values at\n * respective positions to the original array. If any promise in the array\n * rejects, the returned promise is rejected with the rejection reason.\n *\n * @param mixed $promises  Promises or values.\n * @param bool  $recursive If true, resolves new promises that might have been added to the stack during its own resolution.\n *\n * @return PromiseInterface\n *\n * @deprecated all will be removed in guzzlehttp/promises:2.0. Use Utils::all instead.\n */\nfunction all($promises, $recursive = false)\n{\n    return Utils::all($promises, $recursive);\n}\n\n/**\n * Initiate a competitive race between multiple promises or values (values will\n * become immediately fulfilled promises).\n *\n * When count amount of promises have been fulfilled, the returned promise is\n * fulfilled with an array that contains the fulfillment values of the winners\n * in order of resolution.\n *\n * This promise is rejected with a {@see AggregateException} if the number of\n * fulfilled promises is less than the desired $count.\n *\n * @param int   $count    Total number of promises.\n * @param mixed $promises Promises or values.\n *\n * @return PromiseInterface\n *\n * @deprecated some will be removed in guzzlehttp/promises:2.0. Use Utils::some instead.\n */\nfunction some($count, $promises)\n{\n    return Utils::some($count, $promises);\n}\n\n/**\n * Like some(), with 1 as count. However, if the promise fulfills, the\n * fulfillment value is not an array of 1 but the value directly.\n *\n * @param mixed $promises Promises or values.\n *\n * @return PromiseInterface\n *\n * @deprecated any will be removed in guzzlehttp/promises:2.0. Use Utils::any instead.\n */\nfunction any($promises)\n{\n    return Utils::any($promises);\n}\n\n/**\n * Returns a promise that is fulfilled when all of the provided promises have\n * been fulfilled or rejected.\n *\n * The returned promise is fulfilled with an array of inspection state arrays.\n *\n * @see inspect for the inspection state array format.\n *\n * @param mixed $promises Promises or values.\n *\n * @return PromiseInterface\n *\n * @deprecated settle will be removed in guzzlehttp/promises:2.0. Use Utils::settle instead.\n */\nfunction settle($promises)\n{\n    return Utils::settle($promises);\n}\n\n/**\n * Given an iterator that yields promises or values, returns a promise that is\n * fulfilled with a null value when the iterator has been consumed or the\n * aggregate promise has been fulfilled or rejected.\n *\n * $onFulfilled is a function that accepts the fulfilled value, iterator index,\n * and the aggregate promise. The callback can invoke any necessary side\n * effects and choose to resolve or reject the aggregate if needed.\n *\n * $onRejected is a function that accepts the rejection reason, iterator index,\n * and the aggregate promise. The callback can invoke any necessary side\n * effects and choose to resolve or reject the aggregate if needed.\n *\n * @param mixed    $iterable    Iterator or array to iterate over.\n * @param callable $onFulfilled\n * @param callable $onRejected\n *\n * @return PromiseInterface\n *\n * @deprecated each will be removed in guzzlehttp/promises:2.0. Use Each::of instead.\n */\nfunction each(\n    $iterable,\n    callable $onFulfilled = null,\n    callable $onRejected = null\n) {\n    return Each::of($iterable, $onFulfilled, $onRejected);\n}\n\n/**\n * Like each, but only allows a certain number of outstanding promises at any\n * given time.\n *\n * $concurrency may be an integer or a function that accepts the number of\n * pending promises and returns a numeric concurrency limit value to allow for\n * dynamic a concurrency size.\n *\n * @param mixed        $iterable\n * @param int|callable $concurrency\n * @param callable     $onFulfilled\n * @param callable     $onRejected\n *\n * @return PromiseInterface\n *\n * @deprecated each_limit will be removed in guzzlehttp/promises:2.0. Use Each::ofLimit instead.\n */\nfunction each_limit(\n    $iterable,\n    $concurrency,\n    callable $onFulfilled = null,\n    callable $onRejected = null\n) {\n    return Each::ofLimit($iterable, $concurrency, $onFulfilled, $onRejected);\n}\n\n/**\n * Like each_limit, but ensures that no promise in the given $iterable argument\n * is rejected. If any promise is rejected, then the aggregate promise is\n * rejected with the encountered rejection.\n *\n * @param mixed        $iterable\n * @param int|callable $concurrency\n * @param callable     $onFulfilled\n *\n * @return PromiseInterface\n *\n * @deprecated each_limit_all will be removed in guzzlehttp/promises:2.0. Use Each::ofLimitAll instead.\n */\nfunction each_limit_all(\n    $iterable,\n    $concurrency,\n    callable $onFulfilled = null\n) {\n    return Each::ofLimitAll($iterable, $concurrency, $onFulfilled);\n}\n\n/**\n * Returns true if a promise is fulfilled.\n *\n * @return bool\n *\n * @deprecated is_fulfilled will be removed in guzzlehttp/promises:2.0. Use Is::fulfilled instead.\n */\nfunction is_fulfilled(PromiseInterface $promise)\n{\n    return Is::fulfilled($promise);\n}\n\n/**\n * Returns true if a promise is rejected.\n *\n * @return bool\n *\n * @deprecated is_rejected will be removed in guzzlehttp/promises:2.0. Use Is::rejected instead.\n */\nfunction is_rejected(PromiseInterface $promise)\n{\n    return Is::rejected($promise);\n}\n\n/**\n * Returns true if a promise is fulfilled or rejected.\n *\n * @return bool\n *\n * @deprecated is_settled will be removed in guzzlehttp/promises:2.0. Use Is::settled instead.\n */\nfunction is_settled(PromiseInterface $promise)\n{\n    return Is::settled($promise);\n}\n\n/**\n * Create a new coroutine.\n *\n * @see Coroutine\n *\n * @return PromiseInterface\n *\n * @deprecated coroutine will be removed in guzzlehttp/promises:2.0. Use Coroutine::of instead.\n */\nfunction coroutine(callable $generatorFn)\n{\n    return Coroutine::of($generatorFn);\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/promises/src/functions_include.php",
    "content": "<?php\n\n// Don't redefine the functions if included multiple times.\nif (!function_exists('GuzzleHttp\\Promise\\promise_for')) {\n    require __DIR__ . '/functions.php';\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/CHANGELOG.md",
    "content": "# Change Log\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## Unreleased\n\n## 2.1.0 - 2021-10-06\n\n### Changed\n\n- Attempting to create a `Uri` object from a malformed URI will no longer throw a generic\n  `InvalidArgumentException`, but rather a `MalformedUriException`, which inherits from the former\n  for backwards compatibility. Callers relying on the exception being thrown to detect invalid\n  URIs should catch the new exception.\n\n### Fixed\n\n- Return `null` in caching stream size if remote size is `null`\n\n## 2.0.0 - 2021-06-30\n\nIdentical to the RC release.\n\n## 2.0.0@RC-1 - 2021-04-29\n\n### Fixed\n\n- Handle possibly unset `url` in `stream_get_meta_data`\n\n## 2.0.0@beta-1 - 2021-03-21\n\n### Added\n\n- PSR-17 factories\n- Made classes final\n- PHP7 type hints\n\n### Changed\n\n- When building a query string, booleans are represented as 1 and 0.\n\n### Removed\n\n- PHP < 7.2 support\n- All functions in the Guzzle\\Psr7 namespace\n\n## 1.8.1 - 2021-03-21\n\n### Fixed\n\n- Issue parsing IPv6 URLs\n- Issue modifying ServerRequest lost all its attributes\n\n## 1.8.0 - 2021-03-21\n\n### Added\n\n- Locale independent URL parsing\n- Most classes got a `@final` annotation to prepare for 2.0\n\n### Fixed\n\n- Issue when creating stream from `php://input` and curl-ext is not installed\n- Broken `Utils::tryFopen()` on PHP 8\n\n## 1.7.0 - 2020-09-30\n\n### Added\n\n- Replaced functions by static methods\n\n### Fixed\n\n- Converting a non-seekable stream to a string\n- Handle multiple Set-Cookie correctly\n- Ignore array keys in header values when merging\n- Allow multibyte characters to be parsed in `Message:bodySummary()`\n\n### Changed\n\n- Restored partial HHVM 3 support\n\n\n## [1.6.1] - 2019-07-02\n\n### Fixed\n\n- Accept null and bool header values again\n\n\n## [1.6.0] - 2019-06-30\n\n### Added\n\n- Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244)\n- Added MIME type for WEBP image format (#246)\n- Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272)\n\n### Changed\n\n- Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262)\n- Accept port number 0 to be valid (#270)\n\n### Fixed\n\n- Fixed subsequent reads from `php://input` in ServerRequest (#247)\n- Fixed readable/writable detection for certain stream modes (#248)\n- Fixed encoding of special characters in the `userInfo` component of an URI (#253)\n\n\n## [1.5.2] - 2018-12-04\n\n### Fixed\n\n- Check body size when getting the message summary\n\n\n## [1.5.1] - 2018-12-04\n\n### Fixed\n\n- Get the summary of a body only if it is readable\n\n\n## [1.5.0] - 2018-12-03\n\n### Added\n\n- Response first-line to response string exception (fixes #145)\n- A test for #129 behavior\n- `get_message_body_summary` function in order to get the message summary\n- `3gp` and `mkv` mime types\n\n### Changed\n\n- Clarify exception message when stream is detached\n\n### Deprecated\n\n- Deprecated parsing folded header lines as per RFC 7230\n\n### Fixed\n\n- Fix `AppendStream::detach` to not close streams\n- `InflateStream` preserves `isSeekable` attribute of the underlying stream\n- `ServerRequest::getUriFromGlobals` to support URLs in query parameters\n\n\nSeveral other fixes and improvements.\n\n\n## [1.4.2] - 2017-03-20\n\n### Fixed\n\n- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing\n  calls to `trigger_error` when deprecated methods are invoked.\n\n\n## [1.4.1] - 2017-02-27\n\n### Added\n\n- Rriggering of silenced deprecation warnings.\n\n### Fixed\n\n- Reverted BC break by reintroducing behavior to automagically fix a URI with a\n  relative path and an authority by adding a leading slash to the path. It's only\n  deprecated now.\n\n\n## [1.4.0] - 2017-02-21\n\n### Added\n\n- Added common URI utility methods based on RFC 3986 (see documentation in the readme):\n  - `Uri::isDefaultPort`\n  - `Uri::isAbsolute`\n  - `Uri::isNetworkPathReference`\n  - `Uri::isAbsolutePathReference`\n  - `Uri::isRelativePathReference`\n  - `Uri::isSameDocumentReference`\n  - `Uri::composeComponents`\n  - `UriNormalizer::normalize`\n  - `UriNormalizer::isEquivalent`\n  - `UriResolver::relativize`\n\n### Changed\n\n- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form.\n- Allow `parse_response` to parse a response without delimiting space and reason.\n- Ensure each URI modification results in a valid URI according to PSR-7 discussions.\n  Invalid modifications will throw an exception instead of returning a wrong URI or\n  doing some magic.\n  - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception\n    because the path of a URI with an authority must start with a slash \"/\" or be empty\n  - `(new Uri())->withScheme('http')` will return `'http://localhost'`\n\n### Deprecated\n\n- `Uri::resolve` in favor of `UriResolver::resolve`\n- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments`\n\n### Fixed\n\n- `Stream::read` when length parameter <= 0.\n- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory.\n- `ServerRequest::getUriFromGlobals` when `Host` header contains port.\n- Compatibility of URIs with `file` scheme and empty host.\n\n\n## [1.3.1] - 2016-06-25\n\n### Fixed\n\n- `Uri::__toString` for network path references, e.g. `//example.org`.\n- Missing lowercase normalization for host.\n- Handling of URI components in case they are `'0'` in a lot of places,\n  e.g. as a user info password.\n- `Uri::withAddedHeader` to correctly merge headers with different case.\n- Trimming of header values in `Uri::withAddedHeader`. Header values may\n  be surrounded by whitespace which should be ignored according to RFC 7230\n  Section 3.2.4. This does not apply to header names.\n- `Uri::withAddedHeader` with an array of header values.\n- `Uri::resolve` when base path has no slash and handling of fragment.\n- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the\n  key/value both in encoded as well as decoded form to those methods. This is\n  consistent with withPath, withQuery etc.\n- `ServerRequest::withoutAttribute` when attribute value is null.\n\n\n## [1.3.0] - 2016-04-13\n\n### Added\n\n- Remaining interfaces needed for full PSR7 compatibility\n  (ServerRequestInterface, UploadedFileInterface, etc.).\n- Support for stream_for from scalars.\n\n### Changed\n\n- Can now extend Uri.\n\n### Fixed\n- A bug in validating request methods by making it more permissive.\n\n\n## [1.2.3] - 2016-02-18\n\n### Fixed\n\n- Support in `GuzzleHttp\\Psr7\\CachingStream` for seeking forward on remote\n  streams, which can sometimes return fewer bytes than requested with `fread`.\n- Handling of gzipped responses with FNAME headers.\n\n\n## [1.2.2] - 2016-01-22\n\n### Added\n\n- Support for URIs without any authority.\n- Support for HTTP 451 'Unavailable For Legal Reasons.'\n- Support for using '0' as a filename.\n- Support for including non-standard ports in Host headers.\n\n\n## [1.2.1] - 2015-11-02\n\n### Changes\n\n- Now supporting negative offsets when seeking to SEEK_END.\n\n\n## [1.2.0] - 2015-08-15\n\n### Changed\n\n- Body as `\"0\"` is now properly added to a response.\n- Now allowing forward seeking in CachingStream.\n- Now properly parsing HTTP requests that contain proxy targets in\n  `parse_request`.\n- functions.php is now conditionally required.\n- user-info is no longer dropped when resolving URIs.\n\n\n## [1.1.0] - 2015-06-24\n\n### Changed\n\n- URIs can now be relative.\n- `multipart/form-data` headers are now overridden case-insensitively.\n- URI paths no longer encode the following characters because they are allowed\n  in URIs: \"(\", \")\", \"*\", \"!\", \"'\"\n- A port is no longer added to a URI when the scheme is missing and no port is\n  present.\n\n\n## 1.0.0 - 2015-05-19\n\nInitial release.\n\nCurrently unsupported:\n\n- `Psr\\Http\\Message\\ServerRequestInterface`\n- `Psr\\Http\\Message\\UploadedFileInterface`\n\n\n\n[1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0\n[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2\n[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1\n[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0\n[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2\n[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1\n[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0\n[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1\n[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0\n[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3\n[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2\n[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1\n[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0\n[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Michael Dowling <mtdowling@gmail.com>\nCopyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com>\nCopyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk>\nCopyright (c) 2016 Tobias Schultze <webmaster@tubo-world.de>\nCopyright (c) 2016 George Mponos <gmponos@gmail.com>\nCopyright (c) 2018 Tobias Nyholm <tobias.nyholm@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/README.md",
    "content": "# PSR-7 Message Implementation\n\nThis repository contains a full [PSR-7](http://www.php-fig.org/psr/psr-7/)\nmessage implementation, several stream decorators, and some helpful\nfunctionality like query string parsing.\n\n![CI](https://github.com/guzzle/psr7/workflows/CI/badge.svg)\n![Static analysis](https://github.com/guzzle/psr7/workflows/Static%20analysis/badge.svg)\n\n\n# Stream implementation\n\nThis package comes with a number of stream implementations and stream\ndecorators.\n\n\n## AppendStream\n\n`GuzzleHttp\\Psr7\\AppendStream`\n\nReads from multiple streams, one after the other.\n\n```php\nuse GuzzleHttp\\Psr7;\n\n$a = Psr7\\Utils::streamFor('abc, ');\n$b = Psr7\\Utils::streamFor('123.');\n$composed = new Psr7\\AppendStream([$a, $b]);\n\n$composed->addStream(Psr7\\Utils::streamFor(' Above all listen to me'));\n\necho $composed; // abc, 123. Above all listen to me.\n```\n\n\n## BufferStream\n\n`GuzzleHttp\\Psr7\\BufferStream`\n\nProvides a buffer stream that can be written to fill a buffer, and read\nfrom to remove bytes from the buffer.\n\nThis stream returns a \"hwm\" metadata value that tells upstream consumers\nwhat the configured high water mark of the stream is, or the maximum\npreferred size of the buffer.\n\n```php\nuse GuzzleHttp\\Psr7;\n\n// When more than 1024 bytes are in the buffer, it will begin returning\n// false to writes. This is an indication that writers should slow down.\n$buffer = new Psr7\\BufferStream(1024);\n```\n\n\n## CachingStream\n\nThe CachingStream is used to allow seeking over previously read bytes on\nnon-seekable streams. This can be useful when transferring a non-seekable\nentity body fails due to needing to rewind the stream (for example, resulting\nfrom a redirect). Data that is read from the remote stream will be buffered in\na PHP temp stream so that previously read bytes are cached first in memory,\nthen on disk.\n\n```php\nuse GuzzleHttp\\Psr7;\n\n$original = Psr7\\Utils::streamFor(fopen('http://www.google.com', 'r'));\n$stream = new Psr7\\CachingStream($original);\n\n$stream->read(1024);\necho $stream->tell();\n// 1024\n\n$stream->seek(0);\necho $stream->tell();\n// 0\n```\n\n\n## DroppingStream\n\n`GuzzleHttp\\Psr7\\DroppingStream`\n\nStream decorator that begins dropping data once the size of the underlying\nstream becomes too full.\n\n```php\nuse GuzzleHttp\\Psr7;\n\n// Create an empty stream\n$stream = Psr7\\Utils::streamFor();\n\n// Start dropping data when the stream has more than 10 bytes\n$dropping = new Psr7\\DroppingStream($stream, 10);\n\n$dropping->write('01234567890123456789');\necho $stream; // 0123456789\n```\n\n\n## FnStream\n\n`GuzzleHttp\\Psr7\\FnStream`\n\nCompose stream implementations based on a hash of functions.\n\nAllows for easy testing and extension of a provided stream without needing\nto create a concrete class for a simple extension point.\n\n```php\n\nuse GuzzleHttp\\Psr7;\n\n$stream = Psr7\\Utils::streamFor('hi');\n$fnStream = Psr7\\FnStream::decorate($stream, [\n    'rewind' => function () use ($stream) {\n        echo 'About to rewind - ';\n        $stream->rewind();\n        echo 'rewound!';\n    }\n]);\n\n$fnStream->rewind();\n// Outputs: About to rewind - rewound!\n```\n\n\n## InflateStream\n\n`GuzzleHttp\\Psr7\\InflateStream`\n\nUses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content.\n\nThis stream decorator converts the provided stream to a PHP stream resource,\nthen appends the zlib.inflate filter. The stream is then converted back\nto a Guzzle stream resource to be used as a Guzzle stream.\n\n\n## LazyOpenStream\n\n`GuzzleHttp\\Psr7\\LazyOpenStream`\n\nLazily reads or writes to a file that is opened only after an IO operation\ntake place on the stream.\n\n```php\nuse GuzzleHttp\\Psr7;\n\n$stream = new Psr7\\LazyOpenStream('/path/to/file', 'r');\n// The file has not yet been opened...\n\necho $stream->read(10);\n// The file is opened and read from only when needed.\n```\n\n\n## LimitStream\n\n`GuzzleHttp\\Psr7\\LimitStream`\n\nLimitStream can be used to read a subset or slice of an existing stream object.\nThis can be useful for breaking a large file into smaller pieces to be sent in\nchunks (e.g. Amazon S3's multipart upload API).\n\n```php\nuse GuzzleHttp\\Psr7;\n\n$original = Psr7\\Utils::streamFor(fopen('/tmp/test.txt', 'r+'));\necho $original->getSize();\n// >>> 1048576\n\n// Limit the size of the body to 1024 bytes and start reading from byte 2048\n$stream = new Psr7\\LimitStream($original, 1024, 2048);\necho $stream->getSize();\n// >>> 1024\necho $stream->tell();\n// >>> 0\n```\n\n\n## MultipartStream\n\n`GuzzleHttp\\Psr7\\MultipartStream`\n\nStream that when read returns bytes for a streaming multipart or\nmultipart/form-data stream.\n\n\n## NoSeekStream\n\n`GuzzleHttp\\Psr7\\NoSeekStream`\n\nNoSeekStream wraps a stream and does not allow seeking.\n\n```php\nuse GuzzleHttp\\Psr7;\n\n$original = Psr7\\Utils::streamFor('foo');\n$noSeek = new Psr7\\NoSeekStream($original);\n\necho $noSeek->read(3);\n// foo\nvar_export($noSeek->isSeekable());\n// false\n$noSeek->seek(0);\nvar_export($noSeek->read(3));\n// NULL\n```\n\n\n## PumpStream\n\n`GuzzleHttp\\Psr7\\PumpStream`\n\nProvides a read only stream that pumps data from a PHP callable.\n\nWhen invoking the provided callable, the PumpStream will pass the amount of\ndata requested to read to the callable. The callable can choose to ignore\nthis value and return fewer or more bytes than requested. Any extra data\nreturned by the provided callable is buffered internally until drained using\nthe read() function of the PumpStream. The provided callable MUST return\nfalse when there is no more data to read.\n\n\n## Implementing stream decorators\n\nCreating a stream decorator is very easy thanks to the\n`GuzzleHttp\\Psr7\\StreamDecoratorTrait`. This trait provides methods that\nimplement `Psr\\Http\\Message\\StreamInterface` by proxying to an underlying\nstream. Just `use` the `StreamDecoratorTrait` and implement your custom\nmethods.\n\nFor example, let's say we wanted to call a specific function each time the last\nbyte is read from a stream. This could be implemented by overriding the\n`read()` method.\n\n```php\nuse Psr\\Http\\Message\\StreamInterface;\nuse GuzzleHttp\\Psr7\\StreamDecoratorTrait;\n\nclass EofCallbackStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    private $callback;\n\n    public function __construct(StreamInterface $stream, callable $cb)\n    {\n        $this->stream = $stream;\n        $this->callback = $cb;\n    }\n\n    public function read($length)\n    {\n        $result = $this->stream->read($length);\n\n        // Invoke the callback when EOF is hit.\n        if ($this->eof()) {\n            call_user_func($this->callback);\n        }\n\n        return $result;\n    }\n}\n```\n\nThis decorator could be added to any existing stream and used like so:\n\n```php\nuse GuzzleHttp\\Psr7;\n\n$original = Psr7\\Utils::streamFor('foo');\n\n$eofStream = new EofCallbackStream($original, function () {\n    echo 'EOF!';\n});\n\n$eofStream->read(2);\n$eofStream->read(1);\n// echoes \"EOF!\"\n$eofStream->seek(0);\n$eofStream->read(3);\n// echoes \"EOF!\"\n```\n\n\n## PHP StreamWrapper\n\nYou can use the `GuzzleHttp\\Psr7\\StreamWrapper` class if you need to use a\nPSR-7 stream as a PHP stream resource.\n\nUse the `GuzzleHttp\\Psr7\\StreamWrapper::getResource()` method to create a PHP\nstream from a PSR-7 stream.\n\n```php\nuse GuzzleHttp\\Psr7\\StreamWrapper;\n\n$stream = GuzzleHttp\\Psr7\\Utils::streamFor('hello!');\n$resource = StreamWrapper::getResource($stream);\necho fread($resource, 6); // outputs hello!\n```\n\n\n# Static API\n\nThere are various static methods available under the `GuzzleHttp\\Psr7` namespace.\n\n\n## `GuzzleHttp\\Psr7\\Message::toString`\n\n`public static function toString(MessageInterface $message): string`\n\nReturns the string representation of an HTTP message.\n\n```php\n$request = new GuzzleHttp\\Psr7\\Request('GET', 'http://example.com');\necho GuzzleHttp\\Psr7\\Message::toString($request);\n```\n\n\n## `GuzzleHttp\\Psr7\\Message::bodySummary`\n\n`public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null`\n\nGet a short summary of the message body.\n\nWill return `null` if the response is not printable.\n\n\n## `GuzzleHttp\\Psr7\\Message::rewindBody`\n\n`public static function rewindBody(MessageInterface $message): void`\n\nAttempts to rewind a message body and throws an exception on failure.\n\nThe body of the message will only be rewound if a call to `tell()`\nreturns a value other than `0`.\n\n\n## `GuzzleHttp\\Psr7\\Message::parseMessage`\n\n`public static function parseMessage(string $message): array`\n\nParses an HTTP message into an associative array.\n\nThe array contains the \"start-line\" key containing the start line of\nthe message, \"headers\" key containing an associative array of header\narray values, and a \"body\" key containing the body of the message.\n\n\n## `GuzzleHttp\\Psr7\\Message::parseRequestUri`\n\n`public static function parseRequestUri(string $path, array $headers): string`\n\nConstructs a URI for an HTTP request message.\n\n\n## `GuzzleHttp\\Psr7\\Message::parseRequest`\n\n`public static function parseRequest(string $message): Request`\n\nParses a request message string into a request object.\n\n\n## `GuzzleHttp\\Psr7\\Message::parseResponse`\n\n`public static function parseResponse(string $message): Response`\n\nParses a response message string into a response object.\n\n\n## `GuzzleHttp\\Psr7\\Header::parse`\n\n`public static function parse(string|array $header): array`\n\nParse an array of header values containing \";\" separated data into an\narray of associative arrays representing the header key value pair data\nof the header. When a parameter does not contain a value, but just\ncontains a key, this function will inject a key with a '' string value.\n\n\n## `GuzzleHttp\\Psr7\\Header::normalize`\n\n`public static function normalize(string|array $header): array`\n\nConverts an array of header values that may contain comma separated\nheaders into an array of headers with no comma separated values.\n\n\n## `GuzzleHttp\\Psr7\\Query::parse`\n\n`public static function parse(string $str, int|bool $urlEncoding = true): array`\n\nParse a query string into an associative array.\n\nIf multiple values are found for the same key, the value of that key\nvalue pair will become an array. This function does not parse nested\nPHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2`\nwill be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`.\n\n\n## `GuzzleHttp\\Psr7\\Query::build`\n\n`public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string`\n\nBuild a query string from an array of key value pairs.\n\nThis function can use the return value of `parse()` to build a query\nstring. This function does not modify the provided keys when an array is\nencountered (like `http_build_query()` would).\n\n\n## `GuzzleHttp\\Psr7\\Utils::caselessRemove`\n\n`public static function caselessRemove(iterable<string> $keys, $keys, array $data): array`\n\nRemove the items given by the keys, case insensitively from the data.\n\n\n## `GuzzleHttp\\Psr7\\Utils::copyToStream`\n\n`public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void`\n\nCopy the contents of a stream into another stream until the given number\nof bytes have been read.\n\n\n## `GuzzleHttp\\Psr7\\Utils::copyToString`\n\n`public static function copyToString(StreamInterface $stream, int $maxLen = -1): string`\n\nCopy the contents of a stream into a string until the given number of\nbytes have been read.\n\n\n## `GuzzleHttp\\Psr7\\Utils::hash`\n\n`public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string`\n\nCalculate a hash of a stream.\n\nThis method reads the entire stream to calculate a rolling hash, based on\nPHP's `hash_init` functions.\n\n\n## `GuzzleHttp\\Psr7\\Utils::modifyRequest`\n\n`public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface`\n\nClone and modify a request with the given changes.\n\nThis method is useful for reducing the number of clones needed to mutate\na message.\n\n- method: (string) Changes the HTTP method.\n- set_headers: (array) Sets the given headers.\n- remove_headers: (array) Remove the given headers.\n- body: (mixed) Sets the given body.\n- uri: (UriInterface) Set the URI.\n- query: (string) Set the query string value of the URI.\n- version: (string) Set the protocol version.\n\n\n## `GuzzleHttp\\Psr7\\Utils::readLine`\n\n`public static function readLine(StreamInterface $stream, int $maxLength = null): string`\n\nRead a line from the stream up to the maximum allowed buffer length.\n\n\n## `GuzzleHttp\\Psr7\\Utils::streamFor`\n\n`public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\\Iterator $resource = '', array $options = []): StreamInterface`\n\nCreate a new stream based on the input type.\n\nOptions is an associative array that can contain the following keys:\n\n- metadata: Array of custom metadata.\n- size: Size of the stream.\n\nThis method accepts the following `$resource` types:\n\n- `Psr\\Http\\Message\\StreamInterface`: Returns the value as-is.\n- `string`: Creates a stream object that uses the given string as the contents.\n- `resource`: Creates a stream object that wraps the given PHP stream resource.\n- `Iterator`: If the provided value implements `Iterator`, then a read-only\n  stream object will be created that wraps the given iterable. Each time the\n  stream is read from, data from the iterator will fill a buffer and will be\n  continuously called until the buffer is equal to the requested read size.\n  Subsequent read calls will first read from the buffer and then call `next`\n  on the underlying iterator until it is exhausted.\n- `object` with `__toString()`: If the object has the `__toString()` method,\n  the object will be cast to a string and then a stream will be returned that\n  uses the string value.\n- `NULL`: When `null` is passed, an empty stream object is returned.\n- `callable` When a callable is passed, a read-only stream object will be\n  created that invokes the given callable. The callable is invoked with the\n  number of suggested bytes to read. The callable can return any number of\n  bytes, but MUST return `false` when there is no more data to return. The\n  stream object that wraps the callable will invoke the callable until the\n  number of requested bytes are available. Any additional bytes will be\n  buffered and used in subsequent reads.\n\n```php\n$stream = GuzzleHttp\\Psr7\\Utils::streamFor('foo');\n$stream = GuzzleHttp\\Psr7\\Utils::streamFor(fopen('/path/to/file', 'r'));\n\n$generator = function ($bytes) {\n    for ($i = 0; $i < $bytes; $i++) {\n        yield ' ';\n    }\n}\n\n$stream = GuzzleHttp\\Psr7\\Utils::streamFor($generator(100));\n```\n\n\n## `GuzzleHttp\\Psr7\\Utils::tryFopen`\n\n`public static function tryFopen(string $filename, string $mode): resource`\n\nSafely opens a PHP stream resource using a filename.\n\nWhen fopen fails, PHP normally raises a warning. This function adds an\nerror handler that checks for errors and throws an exception instead.\n\n\n## `GuzzleHttp\\Psr7\\Utils::uriFor`\n\n`public static function uriFor(string|UriInterface $uri): UriInterface`\n\nReturns a UriInterface for the given value.\n\nThis function accepts a string or UriInterface and returns a\nUriInterface for the given value. If the value is already a\nUriInterface, it is returned as-is.\n\n\n## `GuzzleHttp\\Psr7\\MimeType::fromFilename`\n\n`public static function fromFilename(string $filename): string|null`\n\nDetermines the mimetype of a file by looking at its extension.\n\n\n## `GuzzleHttp\\Psr7\\MimeType::fromExtension`\n\n`public static function fromExtension(string $extension): string|null`\n\nMaps a file extensions to a mimetype.\n\n\n## Upgrading from Function API\n\nThe static API was first introduced in 1.7.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0. A migration table has been provided here for your convenience:\n\n| Original Function | Replacement Method |\n|----------------|----------------|\n| `str` | `Message::toString` |\n| `uri_for` | `Utils::uriFor` |\n| `stream_for` | `Utils::streamFor` |\n| `parse_header` | `Header::parse` |\n| `normalize_header` | `Header::normalize` |\n| `modify_request` | `Utils::modifyRequest` |\n| `rewind_body` | `Message::rewindBody` |\n| `try_fopen` | `Utils::tryFopen` |\n| `copy_to_string` | `Utils::copyToString` |\n| `copy_to_stream` | `Utils::copyToStream` |\n| `hash` | `Utils::hash` |\n| `readline` | `Utils::readLine` |\n| `parse_request` | `Message::parseRequest` |\n| `parse_response` | `Message::parseResponse` |\n| `parse_query` | `Query::parse` |\n| `build_query` | `Query::build` |\n| `mimetype_from_filename` | `MimeType::fromFilename` |\n| `mimetype_from_extension` | `MimeType::fromExtension` |\n| `_parse_message` | `Message::parseMessage` |\n| `_parse_request_uri` | `Message::parseRequestUri` |\n| `get_message_body_summary` | `Message::bodySummary` |\n| `_caseless_remove` | `Utils::caselessRemove` |\n\n\n# Additional URI Methods\n\nAside from the standard `Psr\\Http\\Message\\UriInterface` implementation in form of the `GuzzleHttp\\Psr7\\Uri` class,\nthis library also provides additional functionality when working with URIs as static methods.\n\n## URI Types\n\nAn instance of `Psr\\Http\\Message\\UriInterface` can either be an absolute URI or a relative reference.\nAn absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,\nthe base URI. Relative references can be divided into several forms according to\n[RFC 3986 Section 4.2](https://tools.ietf.org/html/rfc3986#section-4.2):\n\n- network-path references, e.g. `//example.com/path`\n- absolute-path references, e.g. `/path`\n- relative-path references, e.g. `subpath`\n\nThe following methods can be used to identify the type of the URI.\n\n### `GuzzleHttp\\Psr7\\Uri::isAbsolute`\n\n`public static function isAbsolute(UriInterface $uri): bool`\n\nWhether the URI is absolute, i.e. it has a scheme.\n\n### `GuzzleHttp\\Psr7\\Uri::isNetworkPathReference`\n\n`public static function isNetworkPathReference(UriInterface $uri): bool`\n\nWhether the URI is a network-path reference. A relative reference that begins with two slash characters is\ntermed an network-path reference.\n\n### `GuzzleHttp\\Psr7\\Uri::isAbsolutePathReference`\n\n`public static function isAbsolutePathReference(UriInterface $uri): bool`\n\nWhether the URI is a absolute-path reference. A relative reference that begins with a single slash character is\ntermed an absolute-path reference.\n\n### `GuzzleHttp\\Psr7\\Uri::isRelativePathReference`\n\n`public static function isRelativePathReference(UriInterface $uri): bool`\n\nWhether the URI is a relative-path reference. A relative reference that does not begin with a slash character is\ntermed a relative-path reference.\n\n### `GuzzleHttp\\Psr7\\Uri::isSameDocumentReference`\n\n`public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool`\n\nWhether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its\nfragment component, identical to the base URI. When no base URI is given, only an empty URI reference\n(apart from its fragment) is considered a same-document reference.\n\n## URI Components\n\nAdditional methods to work with URI components.\n\n### `GuzzleHttp\\Psr7\\Uri::isDefaultPort`\n\n`public static function isDefaultPort(UriInterface $uri): bool`\n\nWhether the URI has the default port of the current scheme. `Psr\\Http\\Message\\UriInterface::getPort` may return null\nor the standard port. This method can be used independently of the implementation.\n\n### `GuzzleHttp\\Psr7\\Uri::composeComponents`\n\n`public static function composeComponents($scheme, $authority, $path, $query, $fragment): string`\n\nComposes a URI reference string from its various components according to\n[RFC 3986 Section 5.3](https://tools.ietf.org/html/rfc3986#section-5.3). Usually this method does not need to be called\nmanually but instead is used indirectly via `Psr\\Http\\Message\\UriInterface::__toString`.\n\n### `GuzzleHttp\\Psr7\\Uri::fromParts`\n\n`public static function fromParts(array $parts): UriInterface`\n\nCreates a URI from a hash of [`parse_url`](http://php.net/manual/en/function.parse-url.php) components.\n\n\n### `GuzzleHttp\\Psr7\\Uri::withQueryValue`\n\n`public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface`\n\nCreates a new URI with a specific query string value. Any existing query string values that exactly match the\nprovided key are removed and replaced with the given key value pair. A value of null will set the query string\nkey without a value, e.g. \"key\" instead of \"key=value\".\n\n### `GuzzleHttp\\Psr7\\Uri::withQueryValues`\n\n`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface`\n\nCreates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an\nassociative array of key => value.\n\n### `GuzzleHttp\\Psr7\\Uri::withoutQueryValue`\n\n`public static function withoutQueryValue(UriInterface $uri, $key): UriInterface`\n\nCreates a new URI with a specific query string value removed. Any existing query string values that exactly match the\nprovided key are removed.\n\n## Reference Resolution\n\n`GuzzleHttp\\Psr7\\UriResolver` provides methods to resolve a URI reference in the context of a base URI according\nto [RFC 3986 Section 5](https://tools.ietf.org/html/rfc3986#section-5). This is for example also what web browsers\ndo when resolving a link in a website based on the current request URI.\n\n### `GuzzleHttp\\Psr7\\UriResolver::resolve`\n\n`public static function resolve(UriInterface $base, UriInterface $rel): UriInterface`\n\nConverts the relative URI into a new URI that is resolved against the base URI.\n\n### `GuzzleHttp\\Psr7\\UriResolver::removeDotSegments`\n\n`public static function removeDotSegments(string $path): string`\n\nRemoves dot segments from a path and returns the new path according to\n[RFC 3986 Section 5.2.4](https://tools.ietf.org/html/rfc3986#section-5.2.4).\n\n### `GuzzleHttp\\Psr7\\UriResolver::relativize`\n\n`public static function relativize(UriInterface $base, UriInterface $target): UriInterface`\n\nReturns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():\n\n```php\n(string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))\n```\n\nOne use-case is to use the current request URI as base URI and then generate relative links in your documents\nto reduce the document size or offer self-contained downloadable document archives.\n\n```php\n$base = new Uri('http://example.com/a/b/');\necho UriResolver::relativize($base, new Uri('http://example.com/a/b/c'));  // prints 'c'.\necho UriResolver::relativize($base, new Uri('http://example.com/a/x/y'));  // prints '../x/y'.\necho UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.\necho UriResolver::relativize($base, new Uri('http://example.org/a/b/'));   // prints '//example.org/a/b/'.\n```\n\n## Normalization and Comparison\n\n`GuzzleHttp\\Psr7\\UriNormalizer` provides methods to normalize and compare URIs according to\n[RFC 3986 Section 6](https://tools.ietf.org/html/rfc3986#section-6).\n\n### `GuzzleHttp\\Psr7\\UriNormalizer::normalize`\n\n`public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface`\n\nReturns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.\nThis methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask\nof normalizations to apply. The following normalizations are available:\n\n- `UriNormalizer::PRESERVING_NORMALIZATIONS`\n\n    Default normalizations which only include the ones that preserve semantics.\n\n- `UriNormalizer::CAPITALIZE_PERCENT_ENCODING`\n\n    All letters within a percent-encoding triplet (e.g., \"%3A\") are case-insensitive, and should be capitalized.\n\n    Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b`\n\n- `UriNormalizer::DECODE_UNRESERVED_CHARACTERS`\n\n    Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of\n    ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should\n    not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved\n    characters by URI normalizers.\n\n    Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/`\n\n- `UriNormalizer::CONVERT_EMPTY_PATH`\n\n    Converts the empty path to \"/\" for http and https URIs.\n\n    Example: `http://example.org` → `http://example.org/`\n\n- `UriNormalizer::REMOVE_DEFAULT_HOST`\n\n    Removes the default host of the given URI scheme from the URI. Only the \"file\" scheme defines the default host\n    \"localhost\". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to\n    RFC 3986.\n\n    Example: `file://localhost/myfile` → `file:///myfile`\n\n- `UriNormalizer::REMOVE_DEFAULT_PORT`\n\n    Removes the default port of the given URI scheme from the URI.\n\n    Example: `http://example.org:80/` → `http://example.org/`\n\n- `UriNormalizer::REMOVE_DOT_SEGMENTS`\n\n    Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would\n    change the semantics of the URI reference.\n\n    Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html`\n\n- `UriNormalizer::REMOVE_DUPLICATE_SLASHES`\n\n    Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes\n    and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization\n    may change the semantics. Encoded slashes (%2F) are not removed.\n\n    Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html`\n\n- `UriNormalizer::SORT_QUERY_PARAMETERS`\n\n    Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be\n    significant (this is not defined by the standard). So this normalization is not safe and may change the semantics\n    of the URI.\n\n    Example: `?lang=en&article=fred` → `?article=fred&lang=en`\n\n### `GuzzleHttp\\Psr7\\UriNormalizer::isEquivalent`\n\n`public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool`\n\nWhether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given\n`$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent.\nThis of course assumes they will be resolved against the same base URI. If this is not the case, determination of\nequivalence or difference of relative references does not mean anything.\n\n\n## Security\n\nIf you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information.\n\n## License\n\nGuzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.\n\n## For Enterprise\n\nAvailable as part of the Tidelift Subscription\n\nThe maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-psr7?utm_source=packagist-guzzlehttp-psr7&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/composer.json",
    "content": "{\n    \"name\": \"guzzlehttp/psr7\",\n    \"description\": \"PSR-7 message implementation that also provides common utility methods\",\n    \"keywords\": [\n        \"request\",\n        \"response\",\n        \"message\",\n        \"stream\",\n        \"http\",\n        \"uri\",\n        \"url\",\n        \"psr-7\"\n    ],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Graham Campbell\",\n            \"email\": \"hello@gjcampbell.co.uk\",\n            \"homepage\": \"https://github.com/GrahamCampbell\"\n        },\n        {\n            \"name\": \"Michael Dowling\",\n            \"email\": \"mtdowling@gmail.com\",\n            \"homepage\": \"https://github.com/mtdowling\"\n        },\n        {\n            \"name\": \"George Mponos\",\n            \"email\": \"gmponos@gmail.com\",\n            \"homepage\": \"https://github.com/gmponos\"\n        },\n        {\n            \"name\": \"Tobias Nyholm\",\n            \"email\": \"tobias.nyholm@gmail.com\",\n            \"homepage\": \"https://github.com/Nyholm\"\n        },\n        {\n            \"name\": \"Márk Sági-Kazár\",\n            \"email\": \"mark.sagikazar@gmail.com\",\n            \"homepage\": \"https://github.com/sagikazarmark\"\n        },\n        {\n            \"name\": \"Tobias Schultze\",\n            \"email\": \"webmaster@tubo-world.de\",\n            \"homepage\": \"https://github.com/Tobion\"\n        },\n        {\n            \"name\": \"Márk Sági-Kazár\",\n            \"email\": \"mark.sagikazar@gmail.com\",\n            \"homepage\": \"https://sagikazarmark.hu\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^7.2.5 || ^8.0\",\n        \"psr/http-factory\": \"^1.0\",\n        \"psr/http-message\": \"^1.0\",\n        \"ralouphie/getallheaders\": \"^3.0\"\n    },\n    \"provide\": {\n        \"psr/http-factory-implementation\": \"1.0\",\n        \"psr/http-message-implementation\": \"1.0\"\n    },\n    \"require-dev\": {\n        \"bamarni/composer-bin-plugin\": \"^1.4.1\",\n        \"http-interop/http-factory-tests\": \"^0.9\",\n        \"phpunit/phpunit\": \"^8.5.8 || ^9.3.10\"\n    },\n    \"suggest\": {\n        \"laminas/laminas-httphandlerrunner\": \"Emit PSR-7 responses\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"GuzzleHttp\\\\Psr7\\\\\": \"src/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"GuzzleHttp\\\\Tests\\\\Psr7\\\\\": \"tests/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"2.1-dev\"\n        }\n    },\n    \"config\": {\n        \"preferred-install\": \"dist\",\n        \"sort-packages\": true\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/AppendStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Reads from multiple streams, one after the other.\n *\n * This is a read-only stream decorator.\n */\nfinal class AppendStream implements StreamInterface\n{\n    /** @var StreamInterface[] Streams being decorated */\n    private $streams = [];\n\n    /** @var bool */\n    private $seekable = true;\n\n    /** @var int */\n    private $current = 0;\n\n    /** @var int */\n    private $pos = 0;\n\n    /**\n     * @param StreamInterface[] $streams Streams to decorate. Each stream must\n     *                                   be readable.\n     */\n    public function __construct(array $streams = [])\n    {\n        foreach ($streams as $stream) {\n            $this->addStream($stream);\n        }\n    }\n\n    public function __toString(): string\n    {\n        try {\n            $this->rewind();\n            return $this->getContents();\n        } catch (\\Throwable $e) {\n            if (\\PHP_VERSION_ID >= 70400) {\n                throw $e;\n            }\n            trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);\n            return '';\n        }\n    }\n\n    /**\n     * Add a stream to the AppendStream\n     *\n     * @param StreamInterface $stream Stream to append. Must be readable.\n     *\n     * @throws \\InvalidArgumentException if the stream is not readable\n     */\n    public function addStream(StreamInterface $stream): void\n    {\n        if (!$stream->isReadable()) {\n            throw new \\InvalidArgumentException('Each stream must be readable');\n        }\n\n        // The stream is only seekable if all streams are seekable\n        if (!$stream->isSeekable()) {\n            $this->seekable = false;\n        }\n\n        $this->streams[] = $stream;\n    }\n\n    public function getContents(): string\n    {\n        return Utils::copyToString($this);\n    }\n\n    /**\n     * Closes each attached stream.\n     */\n    public function close(): void\n    {\n        $this->pos = $this->current = 0;\n        $this->seekable = true;\n\n        foreach ($this->streams as $stream) {\n            $stream->close();\n        }\n\n        $this->streams = [];\n    }\n\n    /**\n     * Detaches each attached stream.\n     *\n     * Returns null as it's not clear which underlying stream resource to return.\n     */\n    public function detach()\n    {\n        $this->pos = $this->current = 0;\n        $this->seekable = true;\n\n        foreach ($this->streams as $stream) {\n            $stream->detach();\n        }\n\n        $this->streams = [];\n\n        return null;\n    }\n\n    public function tell(): int\n    {\n        return $this->pos;\n    }\n\n    /**\n     * Tries to calculate the size by adding the size of each stream.\n     *\n     * If any of the streams do not return a valid number, then the size of the\n     * append stream cannot be determined and null is returned.\n     */\n    public function getSize(): ?int\n    {\n        $size = 0;\n\n        foreach ($this->streams as $stream) {\n            $s = $stream->getSize();\n            if ($s === null) {\n                return null;\n            }\n            $size += $s;\n        }\n\n        return $size;\n    }\n\n    public function eof(): bool\n    {\n        return !$this->streams ||\n            ($this->current >= count($this->streams) - 1 &&\n             $this->streams[$this->current]->eof());\n    }\n\n    public function rewind(): void\n    {\n        $this->seek(0);\n    }\n\n    /**\n     * Attempts to seek to the given position. Only supports SEEK_SET.\n     */\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        if (!$this->seekable) {\n            throw new \\RuntimeException('This AppendStream is not seekable');\n        } elseif ($whence !== SEEK_SET) {\n            throw new \\RuntimeException('The AppendStream can only seek with SEEK_SET');\n        }\n\n        $this->pos = $this->current = 0;\n\n        // Rewind each stream\n        foreach ($this->streams as $i => $stream) {\n            try {\n                $stream->rewind();\n            } catch (\\Exception $e) {\n                throw new \\RuntimeException('Unable to seek stream '\n                    . $i . ' of the AppendStream', 0, $e);\n            }\n        }\n\n        // Seek to the actual position by reading from each stream\n        while ($this->pos < $offset && !$this->eof()) {\n            $result = $this->read(min(8096, $offset - $this->pos));\n            if ($result === '') {\n                break;\n            }\n        }\n    }\n\n    /**\n     * Reads from all of the appended streams until the length is met or EOF.\n     */\n    public function read($length): string\n    {\n        $buffer = '';\n        $total = count($this->streams) - 1;\n        $remaining = $length;\n        $progressToNext = false;\n\n        while ($remaining > 0) {\n\n            // Progress to the next stream if needed.\n            if ($progressToNext || $this->streams[$this->current]->eof()) {\n                $progressToNext = false;\n                if ($this->current === $total) {\n                    break;\n                }\n                $this->current++;\n            }\n\n            $result = $this->streams[$this->current]->read($remaining);\n\n            if ($result === '') {\n                $progressToNext = true;\n                continue;\n            }\n\n            $buffer .= $result;\n            $remaining = $length - strlen($buffer);\n        }\n\n        $this->pos += strlen($buffer);\n\n        return $buffer;\n    }\n\n    public function isReadable(): bool\n    {\n        return true;\n    }\n\n    public function isWritable(): bool\n    {\n        return false;\n    }\n\n    public function isSeekable(): bool\n    {\n        return $this->seekable;\n    }\n\n    public function write($string): int\n    {\n        throw new \\RuntimeException('Cannot write to an AppendStream');\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getMetadata($key = null)\n    {\n        return $key ? null : [];\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/BufferStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Provides a buffer stream that can be written to to fill a buffer, and read\n * from to remove bytes from the buffer.\n *\n * This stream returns a \"hwm\" metadata value that tells upstream consumers\n * what the configured high water mark of the stream is, or the maximum\n * preferred size of the buffer.\n */\nfinal class BufferStream implements StreamInterface\n{\n    /** @var int */\n    private $hwm;\n\n    /** @var string */\n    private $buffer = '';\n\n    /**\n     * @param int $hwm High water mark, representing the preferred maximum\n     *                 buffer size. If the size of the buffer exceeds the high\n     *                 water mark, then calls to write will continue to succeed\n     *                 but will return 0 to inform writers to slow down\n     *                 until the buffer has been drained by reading from it.\n     */\n    public function __construct(int $hwm = 16384)\n    {\n        $this->hwm = $hwm;\n    }\n\n    public function __toString(): string\n    {\n        return $this->getContents();\n    }\n\n    public function getContents(): string\n    {\n        $buffer = $this->buffer;\n        $this->buffer = '';\n\n        return $buffer;\n    }\n\n    public function close(): void\n    {\n        $this->buffer = '';\n    }\n\n    public function detach()\n    {\n        $this->close();\n\n        return null;\n    }\n\n    public function getSize(): ?int\n    {\n        return strlen($this->buffer);\n    }\n\n    public function isReadable(): bool\n    {\n        return true;\n    }\n\n    public function isWritable(): bool\n    {\n        return true;\n    }\n\n    public function isSeekable(): bool\n    {\n        return false;\n    }\n\n    public function rewind(): void\n    {\n        $this->seek(0);\n    }\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        throw new \\RuntimeException('Cannot seek a BufferStream');\n    }\n\n    public function eof(): bool\n    {\n        return strlen($this->buffer) === 0;\n    }\n\n    public function tell(): int\n    {\n        throw new \\RuntimeException('Cannot determine the position of a BufferStream');\n    }\n\n    /**\n     * Reads data from the buffer.\n     */\n    public function read($length): string\n    {\n        $currentLength = strlen($this->buffer);\n\n        if ($length >= $currentLength) {\n            // No need to slice the buffer because we don't have enough data.\n            $result = $this->buffer;\n            $this->buffer = '';\n        } else {\n            // Slice up the result to provide a subset of the buffer.\n            $result = substr($this->buffer, 0, $length);\n            $this->buffer = substr($this->buffer, $length);\n        }\n\n        return $result;\n    }\n\n    /**\n     * Writes data to the buffer.\n     */\n    public function write($string): int\n    {\n        $this->buffer .= $string;\n\n        if (strlen($this->buffer) >= $this->hwm) {\n            return 0;\n        }\n\n        return strlen($string);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getMetadata($key = null)\n    {\n        if ($key === 'hwm') {\n            return $this->hwm;\n        }\n\n        return $key ? null : [];\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/CachingStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Stream decorator that can cache previously read bytes from a sequentially\n * read stream.\n */\nfinal class CachingStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    /** @var StreamInterface Stream being wrapped */\n    private $remoteStream;\n\n    /** @var int Number of bytes to skip reading due to a write on the buffer */\n    private $skipReadBytes = 0;\n\n    /**\n     * We will treat the buffer object as the body of the stream\n     *\n     * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream.\n     * @param StreamInterface $target Optionally specify where data is cached\n     */\n    public function __construct(\n        StreamInterface $stream,\n        StreamInterface $target = null\n    ) {\n        $this->remoteStream = $stream;\n        $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+'));\n    }\n\n    public function getSize(): ?int\n    {\n        $remoteSize = $this->remoteStream->getSize();\n\n        if (null === $remoteSize) {\n            return null;\n        }\n\n        return max($this->stream->getSize(), $remoteSize);\n    }\n\n    public function rewind(): void\n    {\n        $this->seek(0);\n    }\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        if ($whence === SEEK_SET) {\n            $byte = $offset;\n        } elseif ($whence === SEEK_CUR) {\n            $byte = $offset + $this->tell();\n        } elseif ($whence === SEEK_END) {\n            $size = $this->remoteStream->getSize();\n            if ($size === null) {\n                $size = $this->cacheEntireStream();\n            }\n            $byte = $size + $offset;\n        } else {\n            throw new \\InvalidArgumentException('Invalid whence');\n        }\n\n        $diff = $byte - $this->stream->getSize();\n\n        if ($diff > 0) {\n            // Read the remoteStream until we have read in at least the amount\n            // of bytes requested, or we reach the end of the file.\n            while ($diff > 0 && !$this->remoteStream->eof()) {\n                $this->read($diff);\n                $diff = $byte - $this->stream->getSize();\n            }\n        } else {\n            // We can just do a normal seek since we've already seen this byte.\n            $this->stream->seek($byte);\n        }\n    }\n\n    public function read($length): string\n    {\n        // Perform a regular read on any previously read data from the buffer\n        $data = $this->stream->read($length);\n        $remaining = $length - strlen($data);\n\n        // More data was requested so read from the remote stream\n        if ($remaining) {\n            // If data was written to the buffer in a position that would have\n            // been filled from the remote stream, then we must skip bytes on\n            // the remote stream to emulate overwriting bytes from that\n            // position. This mimics the behavior of other PHP stream wrappers.\n            $remoteData = $this->remoteStream->read(\n                $remaining + $this->skipReadBytes\n            );\n\n            if ($this->skipReadBytes) {\n                $len = strlen($remoteData);\n                $remoteData = substr($remoteData, $this->skipReadBytes);\n                $this->skipReadBytes = max(0, $this->skipReadBytes - $len);\n            }\n\n            $data .= $remoteData;\n            $this->stream->write($remoteData);\n        }\n\n        return $data;\n    }\n\n    public function write($string): int\n    {\n        // When appending to the end of the currently read stream, you'll want\n        // to skip bytes from being read from the remote stream to emulate\n        // other stream wrappers. Basically replacing bytes of data of a fixed\n        // length.\n        $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();\n        if ($overflow > 0) {\n            $this->skipReadBytes += $overflow;\n        }\n\n        return $this->stream->write($string);\n    }\n\n    public function eof(): bool\n    {\n        return $this->stream->eof() && $this->remoteStream->eof();\n    }\n\n    /**\n     * Close both the remote stream and buffer stream\n     */\n    public function close(): void\n    {\n        $this->remoteStream->close();\n        $this->stream->close();\n    }\n\n    private function cacheEntireStream(): int\n    {\n        $target = new FnStream(['write' => 'strlen']);\n        Utils::copyToStream($this, $target);\n\n        return $this->tell();\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/DroppingStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Stream decorator that begins dropping data once the size of the underlying\n * stream becomes too full.\n */\nfinal class DroppingStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    /** @var int */\n    private $maxLength;\n\n    /**\n     * @param StreamInterface $stream    Underlying stream to decorate.\n     * @param int             $maxLength Maximum size before dropping data.\n     */\n    public function __construct(StreamInterface $stream, int $maxLength)\n    {\n        $this->stream = $stream;\n        $this->maxLength = $maxLength;\n    }\n\n    public function write($string): int\n    {\n        $diff = $this->maxLength - $this->stream->getSize();\n\n        // Begin returning 0 when the underlying stream is too large.\n        if ($diff <= 0) {\n            return 0;\n        }\n\n        // Write the stream or a subset of the stream if needed.\n        if (strlen($string) < $diff) {\n            return $this->stream->write($string);\n        }\n\n        return $this->stream->write(substr($string, 0, $diff));\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7\\Exception;\n\nuse InvalidArgumentException;\n\n/**\n * Exception thrown if a URI cannot be parsed because it's malformed.\n */\nclass MalformedUriException extends InvalidArgumentException\n{\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/FnStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Compose stream implementations based on a hash of functions.\n *\n * Allows for easy testing and extension of a provided stream without needing\n * to create a concrete class for a simple extension point.\n */\nfinal class FnStream implements StreamInterface\n{\n    private const SLOTS = [\n        '__toString', 'close', 'detach', 'rewind',\n        'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',\n        'isReadable', 'read', 'getContents', 'getMetadata'\n    ];\n\n    /** @var array<string, callable> */\n    private $methods;\n\n    /**\n     * @param array<string, callable> $methods Hash of method name to a callable.\n     */\n    public function __construct(array $methods)\n    {\n        $this->methods = $methods;\n\n        // Create the functions on the class\n        foreach ($methods as $name => $fn) {\n            $this->{'_fn_' . $name} = $fn;\n        }\n    }\n\n    /**\n     * Lazily determine which methods are not implemented.\n     *\n     * @throws \\BadMethodCallException\n     */\n    public function __get(string $name): void\n    {\n        throw new \\BadMethodCallException(str_replace('_fn_', '', $name)\n            . '() is not implemented in the FnStream');\n    }\n\n    /**\n     * The close method is called on the underlying stream only if possible.\n     */\n    public function __destruct()\n    {\n        if (isset($this->_fn_close)) {\n            call_user_func($this->_fn_close);\n        }\n    }\n\n    /**\n     * An unserialize would allow the __destruct to run when the unserialized value goes out of scope.\n     *\n     * @throws \\LogicException\n     */\n    public function __wakeup(): void\n    {\n        throw new \\LogicException('FnStream should never be unserialized');\n    }\n\n    /**\n     * Adds custom functionality to an underlying stream by intercepting\n     * specific method calls.\n     *\n     * @param StreamInterface         $stream  Stream to decorate\n     * @param array<string, callable> $methods Hash of method name to a closure\n     *\n     * @return FnStream\n     */\n    public static function decorate(StreamInterface $stream, array $methods)\n    {\n        // If any of the required methods were not provided, then simply\n        // proxy to the decorated stream.\n        foreach (array_diff(self::SLOTS, array_keys($methods)) as $diff) {\n            /** @var callable $callable */\n            $callable = [$stream, $diff];\n            $methods[$diff] = $callable;\n        }\n\n        return new self($methods);\n    }\n\n    public function __toString(): string\n    {\n        try {\n            return call_user_func($this->_fn___toString);\n        } catch (\\Throwable $e) {\n            if (\\PHP_VERSION_ID >= 70400) {\n                throw $e;\n            }\n            trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);\n            return '';\n        }\n    }\n\n    public function close(): void\n    {\n        call_user_func($this->_fn_close);\n    }\n\n    public function detach()\n    {\n        return call_user_func($this->_fn_detach);\n    }\n\n    public function getSize(): ?int\n    {\n        return call_user_func($this->_fn_getSize);\n    }\n\n    public function tell(): int\n    {\n        return call_user_func($this->_fn_tell);\n    }\n\n    public function eof(): bool\n    {\n        return call_user_func($this->_fn_eof);\n    }\n\n    public function isSeekable(): bool\n    {\n        return call_user_func($this->_fn_isSeekable);\n    }\n\n    public function rewind(): void\n    {\n        call_user_func($this->_fn_rewind);\n    }\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        call_user_func($this->_fn_seek, $offset, $whence);\n    }\n\n    public function isWritable(): bool\n    {\n        return call_user_func($this->_fn_isWritable);\n    }\n\n    public function write($string): int\n    {\n        return call_user_func($this->_fn_write, $string);\n    }\n\n    public function isReadable(): bool\n    {\n        return call_user_func($this->_fn_isReadable);\n    }\n\n    public function read($length): string\n    {\n        return call_user_func($this->_fn_read, $length);\n    }\n\n    public function getContents(): string\n    {\n        return call_user_func($this->_fn_getContents);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getMetadata($key = null)\n    {\n        return call_user_func($this->_fn_getMetadata, $key);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Header.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nfinal class Header\n{\n    /**\n     * Parse an array of header values containing \";\" separated data into an\n     * array of associative arrays representing the header key value pair data\n     * of the header. When a parameter does not contain a value, but just\n     * contains a key, this function will inject a key with a '' string value.\n     *\n     * @param string|array $header Header to parse into components.\n     */\n    public static function parse($header): array\n    {\n        static $trimmed = \"\\\"'  \\n\\t\\r\";\n        $params = $matches = [];\n\n        foreach (self::normalize($header) as $val) {\n            $part = [];\n            foreach (preg_split('/;(?=([^\"]*\"[^\"]*\")*[^\"]*$)/', $val) as $kvp) {\n                if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {\n                    $m = $matches[0];\n                    if (isset($m[1])) {\n                        $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);\n                    } else {\n                        $part[] = trim($m[0], $trimmed);\n                    }\n                }\n            }\n            if ($part) {\n                $params[] = $part;\n            }\n        }\n\n        return $params;\n    }\n\n    /**\n     * Converts an array of header values that may contain comma separated\n     * headers into an array of headers with no comma separated values.\n     *\n     * @param string|array $header Header to normalize.\n     */\n    public static function normalize($header): array\n    {\n        if (!is_array($header)) {\n            return array_map('trim', explode(',', $header));\n        }\n\n        $result = [];\n        foreach ($header as $value) {\n            foreach ((array) $value as $v) {\n                if (strpos($v, ',') === false) {\n                    $result[] = $v;\n                    continue;\n                }\n                foreach (preg_split('/,(?=([^\"]*\"[^\"]*\")*[^\"]*$)/', $v) as $vv) {\n                    $result[] = trim($vv);\n                }\n            }\n        }\n\n        return $result;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/HttpFactory.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\RequestFactoryInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseFactoryInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\ServerRequestFactoryInterface;\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Message\\StreamFactoryInterface;\nuse Psr\\Http\\Message\\StreamInterface;\nuse Psr\\Http\\Message\\UploadedFileFactoryInterface;\nuse Psr\\Http\\Message\\UploadedFileInterface;\nuse Psr\\Http\\Message\\UriFactoryInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Implements all of the PSR-17 interfaces.\n *\n * Note: in consuming code it is recommended to require the implemented interfaces\n * and inject the instance of this class multiple times.\n */\nfinal class HttpFactory implements\n    RequestFactoryInterface,\n    ResponseFactoryInterface,\n    ServerRequestFactoryInterface,\n    StreamFactoryInterface,\n    UploadedFileFactoryInterface,\n    UriFactoryInterface\n{\n    public function createUploadedFile(\n        StreamInterface $stream,\n        int $size = null,\n        int $error = \\UPLOAD_ERR_OK,\n        string $clientFilename = null,\n        string $clientMediaType = null\n    ): UploadedFileInterface {\n        if ($size === null) {\n            $size = $stream->getSize();\n        }\n\n        return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);\n    }\n\n    public function createStream(string $content = ''): StreamInterface\n    {\n        return Utils::streamFor($content);\n    }\n\n    public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface\n    {\n        try {\n            $resource = Utils::tryFopen($file, $mode);\n        } catch (\\RuntimeException $e) {\n            if ('' === $mode || false === \\in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) {\n                throw new \\InvalidArgumentException(sprintf('Invalid file opening mode \"%s\"', $mode), 0, $e);\n            }\n\n            throw $e;\n        }\n\n        return Utils::streamFor($resource);\n    }\n\n    public function createStreamFromResource($resource): StreamInterface\n    {\n        return Utils::streamFor($resource);\n    }\n\n    public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface\n    {\n        if (empty($method)) {\n            if (!empty($serverParams['REQUEST_METHOD'])) {\n                $method = $serverParams['REQUEST_METHOD'];\n            } else {\n                throw new \\InvalidArgumentException('Cannot determine HTTP method');\n            }\n        }\n\n        return new ServerRequest($method, $uri, [], null, '1.1', $serverParams);\n    }\n\n    public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface\n    {\n        return new Response($code, [], null, '1.1', $reasonPhrase);\n    }\n\n    public function createRequest(string $method, $uri): RequestInterface\n    {\n        return new Request($method, $uri);\n    }\n\n    public function createUri(string $uri = ''): UriInterface\n    {\n        return new Uri($uri);\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/InflateStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content.\n *\n * This stream decorator converts the provided stream to a PHP stream resource,\n * then appends the zlib.inflate filter. The stream is then converted back\n * to a Guzzle stream resource to be used as a Guzzle stream.\n *\n * @link http://tools.ietf.org/html/rfc1950\n * @link http://tools.ietf.org/html/rfc1952\n * @link http://php.net/manual/en/filters.compression.php\n */\nfinal class InflateStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    public function __construct(StreamInterface $stream)\n    {\n        $resource = StreamWrapper::getResource($stream);\n        // Specify window=15+32, so zlib will use header detection to both gzip (with header) and zlib data\n        // See http://www.zlib.net/manual.html#Advanced definition of inflateInit2\n        // \"Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection\"\n        // Default window size is 15.\n        stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15 + 32]);\n        $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource));\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/LazyOpenStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Lazily reads or writes to a file that is opened only after an IO operation\n * take place on the stream.\n */\nfinal class LazyOpenStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    /** @var string */\n    private $filename;\n\n    /** @var string */\n    private $mode;\n\n    /**\n     * @param string $filename File to lazily open\n     * @param string $mode     fopen mode to use when opening the stream\n     */\n    public function __construct(string $filename, string $mode)\n    {\n        $this->filename = $filename;\n        $this->mode = $mode;\n    }\n\n    /**\n     * Creates the underlying stream lazily when required.\n     */\n    protected function createStream(): StreamInterface\n    {\n        return Utils::streamFor(Utils::tryFopen($this->filename, $this->mode));\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/LimitStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Decorator used to return only a subset of a stream.\n */\nfinal class LimitStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    /** @var int Offset to start reading from */\n    private $offset;\n\n    /** @var int Limit the number of bytes that can be read */\n    private $limit;\n\n    /**\n     * @param StreamInterface $stream Stream to wrap\n     * @param int             $limit  Total number of bytes to allow to be read\n     *                                from the stream. Pass -1 for no limit.\n     * @param int             $offset Position to seek to before reading (only\n     *                                works on seekable streams).\n     */\n    public function __construct(\n        StreamInterface $stream,\n        int $limit = -1,\n        int $offset = 0\n    ) {\n        $this->stream = $stream;\n        $this->setLimit($limit);\n        $this->setOffset($offset);\n    }\n\n    public function eof(): bool\n    {\n        // Always return true if the underlying stream is EOF\n        if ($this->stream->eof()) {\n            return true;\n        }\n\n        // No limit and the underlying stream is not at EOF\n        if ($this->limit === -1) {\n            return false;\n        }\n\n        return $this->stream->tell() >= $this->offset + $this->limit;\n    }\n\n    /**\n     * Returns the size of the limited subset of data\n     */\n    public function getSize(): ?int\n    {\n        if (null === ($length = $this->stream->getSize())) {\n            return null;\n        } elseif ($this->limit === -1) {\n            return $length - $this->offset;\n        } else {\n            return min($this->limit, $length - $this->offset);\n        }\n    }\n\n    /**\n     * Allow for a bounded seek on the read limited stream\n     */\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        if ($whence !== SEEK_SET || $offset < 0) {\n            throw new \\RuntimeException(sprintf(\n                'Cannot seek to offset %s with whence %s',\n                $offset,\n                $whence\n            ));\n        }\n\n        $offset += $this->offset;\n\n        if ($this->limit !== -1) {\n            if ($offset > $this->offset + $this->limit) {\n                $offset = $this->offset + $this->limit;\n            }\n        }\n\n        $this->stream->seek($offset);\n    }\n\n    /**\n     * Give a relative tell()\n     */\n    public function tell(): int\n    {\n        return $this->stream->tell() - $this->offset;\n    }\n\n    /**\n     * Set the offset to start limiting from\n     *\n     * @param int $offset Offset to seek to and begin byte limiting from\n     *\n     * @throws \\RuntimeException if the stream cannot be seeked.\n     */\n    public function setOffset(int $offset): void\n    {\n        $current = $this->stream->tell();\n\n        if ($current !== $offset) {\n            // If the stream cannot seek to the offset position, then read to it\n            if ($this->stream->isSeekable()) {\n                $this->stream->seek($offset);\n            } elseif ($current > $offset) {\n                throw new \\RuntimeException(\"Could not seek to stream offset $offset\");\n            } else {\n                $this->stream->read($offset - $current);\n            }\n        }\n\n        $this->offset = $offset;\n    }\n\n    /**\n     * Set the limit of bytes that the decorator allows to be read from the\n     * stream.\n     *\n     * @param int $limit Number of bytes to allow to be read from the stream.\n     *                   Use -1 for no limit.\n     */\n    public function setLimit(int $limit): void\n    {\n        $this->limit = $limit;\n    }\n\n    public function read($length): string\n    {\n        if ($this->limit === -1) {\n            return $this->stream->read($length);\n        }\n\n        // Check if the current position is less than the total allowed\n        // bytes + original offset\n        $remaining = ($this->offset + $this->limit) - $this->stream->tell();\n        if ($remaining > 0) {\n            // Only return the amount of requested data, ensuring that the byte\n            // limit is not exceeded\n            return $this->stream->read(min($remaining, $length));\n        }\n\n        return '';\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Message.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\MessageInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\nfinal class Message\n{\n    /**\n     * Returns the string representation of an HTTP message.\n     *\n     * @param MessageInterface $message Message to convert to a string.\n     */\n    public static function toString(MessageInterface $message): string\n    {\n        if ($message instanceof RequestInterface) {\n            $msg = trim($message->getMethod() . ' '\n                    . $message->getRequestTarget())\n                . ' HTTP/' . $message->getProtocolVersion();\n            if (!$message->hasHeader('host')) {\n                $msg .= \"\\r\\nHost: \" . $message->getUri()->getHost();\n            }\n        } elseif ($message instanceof ResponseInterface) {\n            $msg = 'HTTP/' . $message->getProtocolVersion() . ' '\n                . $message->getStatusCode() . ' '\n                . $message->getReasonPhrase();\n        } else {\n            throw new \\InvalidArgumentException('Unknown message type');\n        }\n\n        foreach ($message->getHeaders() as $name => $values) {\n            if (strtolower($name) === 'set-cookie') {\n                foreach ($values as $value) {\n                    $msg .= \"\\r\\n{$name}: \" . $value;\n                }\n            } else {\n                $msg .= \"\\r\\n{$name}: \" . implode(', ', $values);\n            }\n        }\n\n        return \"{$msg}\\r\\n\\r\\n\" . $message->getBody();\n    }\n\n    /**\n     * Get a short summary of the message body.\n     *\n     * Will return `null` if the response is not printable.\n     *\n     * @param MessageInterface $message    The message to get the body summary\n     * @param int              $truncateAt The maximum allowed size of the summary\n     */\n    public static function bodySummary(MessageInterface $message, int $truncateAt = 120): ?string\n    {\n        $body = $message->getBody();\n\n        if (!$body->isSeekable() || !$body->isReadable()) {\n            return null;\n        }\n\n        $size = $body->getSize();\n\n        if ($size === 0) {\n            return null;\n        }\n\n        $summary = $body->read($truncateAt);\n        $body->rewind();\n\n        if ($size > $truncateAt) {\n            $summary .= ' (truncated...)';\n        }\n\n        // Matches any printable character, including unicode characters:\n        // letters, marks, numbers, punctuation, spacing, and separators.\n        if (preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/u', $summary)) {\n            return null;\n        }\n\n        return $summary;\n    }\n\n    /**\n     * Attempts to rewind a message body and throws an exception on failure.\n     *\n     * The body of the message will only be rewound if a call to `tell()`\n     * returns a value other than `0`.\n     *\n     * @param MessageInterface $message Message to rewind\n     *\n     * @throws \\RuntimeException\n     */\n    public static function rewindBody(MessageInterface $message): void\n    {\n        $body = $message->getBody();\n\n        if ($body->tell()) {\n            $body->rewind();\n        }\n    }\n\n    /**\n     * Parses an HTTP message into an associative array.\n     *\n     * The array contains the \"start-line\" key containing the start line of\n     * the message, \"headers\" key containing an associative array of header\n     * array values, and a \"body\" key containing the body of the message.\n     *\n     * @param string $message HTTP request or response to parse.\n     */\n    public static function parseMessage(string $message): array\n    {\n        if (!$message) {\n            throw new \\InvalidArgumentException('Invalid message');\n        }\n\n        $message = ltrim($message, \"\\r\\n\");\n\n        $messageParts = preg_split(\"/\\r?\\n\\r?\\n/\", $message, 2);\n\n        if ($messageParts === false || count($messageParts) !== 2) {\n            throw new \\InvalidArgumentException('Invalid message: Missing header delimiter');\n        }\n\n        [$rawHeaders, $body] = $messageParts;\n        $rawHeaders .= \"\\r\\n\"; // Put back the delimiter we split previously\n        $headerParts = preg_split(\"/\\r?\\n/\", $rawHeaders, 2);\n\n        if ($headerParts === false || count($headerParts) !== 2) {\n            throw new \\InvalidArgumentException('Invalid message: Missing status line');\n        }\n\n        [$startLine, $rawHeaders] = $headerParts;\n\n        if (preg_match(\"/(?:^HTTP\\/|^[A-Z]+ \\S+ HTTP\\/)(\\d+(?:\\.\\d+)?)/i\", $startLine, $matches) && $matches[1] === '1.0') {\n            // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0\n            $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);\n        }\n\n        /** @var array[] $headerLines */\n        $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);\n\n        // If these aren't the same, then one line didn't match and there's an invalid header.\n        if ($count !== substr_count($rawHeaders, \"\\n\")) {\n            // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4\n            if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {\n                throw new \\InvalidArgumentException('Invalid header syntax: Obsolete line folding');\n            }\n\n            throw new \\InvalidArgumentException('Invalid header syntax');\n        }\n\n        $headers = [];\n\n        foreach ($headerLines as $headerLine) {\n            $headers[$headerLine[1]][] = $headerLine[2];\n        }\n\n        return [\n            'start-line' => $startLine,\n            'headers' => $headers,\n            'body' => $body,\n        ];\n    }\n\n    /**\n     * Constructs a URI for an HTTP request message.\n     *\n     * @param string $path    Path from the start-line\n     * @param array  $headers Array of headers (each value an array).\n     */\n    public static function parseRequestUri(string $path, array $headers): string\n    {\n        $hostKey = array_filter(array_keys($headers), function ($k) {\n            return strtolower($k) === 'host';\n        });\n\n        // If no host is found, then a full URI cannot be constructed.\n        if (!$hostKey) {\n            return $path;\n        }\n\n        $host = $headers[reset($hostKey)][0];\n        $scheme = substr($host, -4) === ':443' ? 'https' : 'http';\n\n        return $scheme . '://' . $host . '/' . ltrim($path, '/');\n    }\n\n    /**\n     * Parses a request message string into a request object.\n     *\n     * @param string $message Request message string.\n     */\n    public static function parseRequest(string $message): RequestInterface\n    {\n        $data = self::parseMessage($message);\n        $matches = [];\n        if (!preg_match('/^[\\S]+\\s+([a-zA-Z]+:\\/\\/|\\/).*/', $data['start-line'], $matches)) {\n            throw new \\InvalidArgumentException('Invalid request string');\n        }\n        $parts = explode(' ', $data['start-line'], 3);\n        $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1';\n\n        $request = new Request(\n            $parts[0],\n            $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1],\n            $data['headers'],\n            $data['body'],\n            $version\n        );\n\n        return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);\n    }\n\n    /**\n     * Parses a response message string into a response object.\n     *\n     * @param string $message Response message string.\n     */\n    public static function parseResponse(string $message): ResponseInterface\n    {\n        $data = self::parseMessage($message);\n        // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space\n        // between status-code and reason-phrase is required. But browsers accept\n        // responses without space and reason as well.\n        if (!preg_match('/^HTTP\\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {\n            throw new \\InvalidArgumentException('Invalid response string: ' . $data['start-line']);\n        }\n        $parts = explode(' ', $data['start-line'], 3);\n\n        return new Response(\n            (int) $parts[1],\n            $data['headers'],\n            $data['body'],\n            explode('/', $parts[0])[1],\n            $parts[2] ?? null\n        );\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/MessageTrait.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\MessageInterface;\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Trait implementing functionality common to requests and responses.\n */\ntrait MessageTrait\n{\n    /** @var array<string, string[]> Map of all registered headers, as original name => array of values */\n    private $headers = [];\n\n    /** @var array<string, string> Map of lowercase header name => original name at registration */\n    private $headerNames  = [];\n\n    /** @var string */\n    private $protocol = '1.1';\n\n    /** @var StreamInterface|null */\n    private $stream;\n\n    public function getProtocolVersion(): string\n    {\n        return $this->protocol;\n    }\n\n    public function withProtocolVersion($version): MessageInterface\n    {\n        if ($this->protocol === $version) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->protocol = $version;\n        return $new;\n    }\n\n    public function getHeaders(): array\n    {\n        return $this->headers;\n    }\n\n    public function hasHeader($header): bool\n    {\n        return isset($this->headerNames[strtolower($header)]);\n    }\n\n    public function getHeader($header): array\n    {\n        $header = strtolower($header);\n\n        if (!isset($this->headerNames[$header])) {\n            return [];\n        }\n\n        $header = $this->headerNames[$header];\n\n        return $this->headers[$header];\n    }\n\n    public function getHeaderLine($header): string\n    {\n        return implode(', ', $this->getHeader($header));\n    }\n\n    public function withHeader($header, $value): MessageInterface\n    {\n        $this->assertHeader($header);\n        $value = $this->normalizeHeaderValue($value);\n        $normalized = strtolower($header);\n\n        $new = clone $this;\n        if (isset($new->headerNames[$normalized])) {\n            unset($new->headers[$new->headerNames[$normalized]]);\n        }\n        $new->headerNames[$normalized] = $header;\n        $new->headers[$header] = $value;\n\n        return $new;\n    }\n\n    public function withAddedHeader($header, $value): MessageInterface\n    {\n        $this->assertHeader($header);\n        $value = $this->normalizeHeaderValue($value);\n        $normalized = strtolower($header);\n\n        $new = clone $this;\n        if (isset($new->headerNames[$normalized])) {\n            $header = $this->headerNames[$normalized];\n            $new->headers[$header] = array_merge($this->headers[$header], $value);\n        } else {\n            $new->headerNames[$normalized] = $header;\n            $new->headers[$header] = $value;\n        }\n\n        return $new;\n    }\n\n    public function withoutHeader($header): MessageInterface\n    {\n        $normalized = strtolower($header);\n\n        if (!isset($this->headerNames[$normalized])) {\n            return $this;\n        }\n\n        $header = $this->headerNames[$normalized];\n\n        $new = clone $this;\n        unset($new->headers[$header], $new->headerNames[$normalized]);\n\n        return $new;\n    }\n\n    public function getBody(): StreamInterface\n    {\n        if (!$this->stream) {\n            $this->stream = Utils::streamFor('');\n        }\n\n        return $this->stream;\n    }\n\n    public function withBody(StreamInterface $body): MessageInterface\n    {\n        if ($body === $this->stream) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->stream = $body;\n        return $new;\n    }\n\n    /**\n     * @param array<string|int, string|string[]> $headers\n     */\n    private function setHeaders(array $headers): void\n    {\n        $this->headerNames = $this->headers = [];\n        foreach ($headers as $header => $value) {\n            if (is_int($header)) {\n                // Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec\n                // and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass.\n                $header = (string) $header;\n            }\n            $this->assertHeader($header);\n            $value = $this->normalizeHeaderValue($value);\n            $normalized = strtolower($header);\n            if (isset($this->headerNames[$normalized])) {\n                $header = $this->headerNames[$normalized];\n                $this->headers[$header] = array_merge($this->headers[$header], $value);\n            } else {\n                $this->headerNames[$normalized] = $header;\n                $this->headers[$header] = $value;\n            }\n        }\n    }\n\n    /**\n     * @param mixed $value\n     *\n     * @return string[]\n     */\n    private function normalizeHeaderValue($value): array\n    {\n        if (!is_array($value)) {\n            return $this->trimHeaderValues([$value]);\n        }\n\n        if (count($value) === 0) {\n            throw new \\InvalidArgumentException('Header value can not be an empty array.');\n        }\n\n        return $this->trimHeaderValues($value);\n    }\n\n    /**\n     * Trims whitespace from the header values.\n     *\n     * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.\n     *\n     * header-field = field-name \":\" OWS field-value OWS\n     * OWS          = *( SP / HTAB )\n     *\n     * @param mixed[] $values Header values\n     *\n     * @return string[] Trimmed header values\n     *\n     * @see https://tools.ietf.org/html/rfc7230#section-3.2.4\n     */\n    private function trimHeaderValues(array $values): array\n    {\n        return array_map(function ($value) {\n            if (!is_scalar($value) && null !== $value) {\n                throw new \\InvalidArgumentException(sprintf(\n                    'Header value must be scalar or null but %s provided.',\n                    is_object($value) ? get_class($value) : gettype($value)\n                ));\n            }\n\n            return trim((string) $value, \" \\t\");\n        }, array_values($values));\n    }\n\n    /**\n     * @see https://tools.ietf.org/html/rfc7230#section-3.2\n     *\n     * @param mixed $header\n     */\n    private function assertHeader($header): void\n    {\n        if (!is_string($header)) {\n            throw new \\InvalidArgumentException(sprintf(\n                'Header name must be a string but %s provided.',\n                is_object($header) ? get_class($header) : gettype($header)\n            ));\n        }\n\n        if (! preg_match('/^[a-zA-Z0-9\\'`#$%&*+.^_|~!-]+$/', $header)) {\n            throw new \\InvalidArgumentException(\n                sprintf(\n                    '\"%s\" is not valid header name',\n                    $header\n                )\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/MimeType.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nfinal class MimeType\n{\n    private const MIME_TYPES = [\n      '3gp' => 'video/3gpp',\n      '7z' => 'application/x-7z-compressed',\n      'aac' => 'audio/x-aac',\n      'ai' => 'application/postscript',\n      'aif' => 'audio/x-aiff',\n      'asc' => 'text/plain',\n      'asf' => 'video/x-ms-asf',\n      'atom' => 'application/atom+xml',\n      'avi' => 'video/x-msvideo',\n      'bmp' => 'image/bmp',\n      'bz2' => 'application/x-bzip2',\n      'cer' => 'application/pkix-cert',\n      'crl' => 'application/pkix-crl',\n      'crt' => 'application/x-x509-ca-cert',\n      'css' => 'text/css',\n      'csv' => 'text/csv',\n      'cu' => 'application/cu-seeme',\n      'deb' => 'application/x-debian-package',\n      'doc' => 'application/msword',\n      'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n      'dvi' => 'application/x-dvi',\n      'eot' => 'application/vnd.ms-fontobject',\n      'eps' => 'application/postscript',\n      'epub' => 'application/epub+zip',\n      'etx' => 'text/x-setext',\n      'flac' => 'audio/flac',\n      'flv' => 'video/x-flv',\n      'gif' => 'image/gif',\n      'gz' => 'application/gzip',\n      'htm' => 'text/html',\n      'html' => 'text/html',\n      'ico' => 'image/x-icon',\n      'ics' => 'text/calendar',\n      'ini' => 'text/plain',\n      'iso' => 'application/x-iso9660-image',\n      'jar' => 'application/java-archive',\n      'jpe' => 'image/jpeg',\n      'jpeg' => 'image/jpeg',\n      'jpg' => 'image/jpeg',\n      'js' => 'text/javascript',\n      'json' => 'application/json',\n      'latex' => 'application/x-latex',\n      'log' => 'text/plain',\n      'm4a' => 'audio/mp4',\n      'm4v' => 'video/mp4',\n      'mid' => 'audio/midi',\n      'midi' => 'audio/midi',\n      'mov' => 'video/quicktime',\n      'mkv' => 'video/x-matroska',\n      'mp3' => 'audio/mpeg',\n      'mp4' => 'video/mp4',\n      'mp4a' => 'audio/mp4',\n      'mp4v' => 'video/mp4',\n      'mpe' => 'video/mpeg',\n      'mpeg' => 'video/mpeg',\n      'mpg' => 'video/mpeg',\n      'mpg4' => 'video/mp4',\n      'oga' => 'audio/ogg',\n      'ogg' => 'audio/ogg',\n      'ogv' => 'video/ogg',\n      'ogx' => 'application/ogg',\n      'pbm' => 'image/x-portable-bitmap',\n      'pdf' => 'application/pdf',\n      'pgm' => 'image/x-portable-graymap',\n      'png' => 'image/png',\n      'pnm' => 'image/x-portable-anymap',\n      'ppm' => 'image/x-portable-pixmap',\n      'ppt' => 'application/vnd.ms-powerpoint',\n      'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n      'ps' => 'application/postscript',\n      'qt' => 'video/quicktime',\n      'rar' => 'application/x-rar-compressed',\n      'ras' => 'image/x-cmu-raster',\n      'rss' => 'application/rss+xml',\n      'rtf' => 'application/rtf',\n      'sgm' => 'text/sgml',\n      'sgml' => 'text/sgml',\n      'svg' => 'image/svg+xml',\n      'swf' => 'application/x-shockwave-flash',\n      'tar' => 'application/x-tar',\n      'tif' => 'image/tiff',\n      'tiff' => 'image/tiff',\n      'torrent' => 'application/x-bittorrent',\n      'ttf' => 'application/x-font-ttf',\n      'txt' => 'text/plain',\n      'wav' => 'audio/x-wav',\n      'webm' => 'video/webm',\n      'webp' => 'image/webp',\n      'wma' => 'audio/x-ms-wma',\n      'wmv' => 'video/x-ms-wmv',\n      'woff' => 'application/x-font-woff',\n      'wsdl' => 'application/wsdl+xml',\n      'xbm' => 'image/x-xbitmap',\n      'xls' => 'application/vnd.ms-excel',\n      'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n      'xml' => 'application/xml',\n      'xpm' => 'image/x-xpixmap',\n      'xwd' => 'image/x-xwindowdump',\n      'yaml' => 'text/yaml',\n      'yml' => 'text/yaml',\n      'zip' => 'application/zip',\n    ];\n\n    /**\n     * Determines the mimetype of a file by looking at its extension.\n     */\n    public static function fromFilename(string $filename): ?string\n    {\n        return self::fromExtension(pathinfo($filename, PATHINFO_EXTENSION));\n    }\n\n    /**\n     * Maps a file extensions to a mimetype.\n     *\n     * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types\n     */\n    public static function fromExtension(string $extension): ?string\n    {\n        return self::MIME_TYPES[strtolower($extension)] ?? null;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/MultipartStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Stream that when read returns bytes for a streaming multipart or\n * multipart/form-data stream.\n */\nfinal class MultipartStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    /** @var string */\n    private $boundary;\n\n    /**\n     * @param array  $elements Array of associative arrays, each containing a\n     *                         required \"name\" key mapping to the form field,\n     *                         name, a required \"contents\" key mapping to a\n     *                         StreamInterface/resource/string, an optional\n     *                         \"headers\" associative array of custom headers,\n     *                         and an optional \"filename\" key mapping to a\n     *                         string to send as the filename in the part.\n     * @param string $boundary You can optionally provide a specific boundary\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public function __construct(array $elements = [], string $boundary = null)\n    {\n        $this->boundary = $boundary ?: sha1(uniqid('', true));\n        $this->stream = $this->createStream($elements);\n    }\n\n    public function getBoundary(): string\n    {\n        return $this->boundary;\n    }\n\n    public function isWritable(): bool\n    {\n        return false;\n    }\n\n    /**\n     * Get the headers needed before transferring the content of a POST file\n     *\n     * @param array<string, string> $headers\n     */\n    private function getHeaders(array $headers): string\n    {\n        $str = '';\n        foreach ($headers as $key => $value) {\n            $str .= \"{$key}: {$value}\\r\\n\";\n        }\n\n        return \"--{$this->boundary}\\r\\n\" . trim($str) . \"\\r\\n\\r\\n\";\n    }\n\n    /**\n     * Create the aggregate stream that will be used to upload the POST data\n     */\n    protected function createStream(array $elements = []): StreamInterface\n    {\n        $stream = new AppendStream();\n\n        foreach ($elements as $element) {\n            $this->addElement($stream, $element);\n        }\n\n        // Add the trailing boundary with CRLF\n        $stream->addStream(Utils::streamFor(\"--{$this->boundary}--\\r\\n\"));\n\n        return $stream;\n    }\n\n    private function addElement(AppendStream $stream, array $element): void\n    {\n        foreach (['contents', 'name'] as $key) {\n            if (!array_key_exists($key, $element)) {\n                throw new \\InvalidArgumentException(\"A '{$key}' key is required\");\n            }\n        }\n\n        $element['contents'] = Utils::streamFor($element['contents']);\n\n        if (empty($element['filename'])) {\n            $uri = $element['contents']->getMetadata('uri');\n            if (substr($uri, 0, 6) !== 'php://') {\n                $element['filename'] = $uri;\n            }\n        }\n\n        [$body, $headers] = $this->createElement(\n            $element['name'],\n            $element['contents'],\n            $element['filename'] ?? null,\n            $element['headers'] ?? []\n        );\n\n        $stream->addStream(Utils::streamFor($this->getHeaders($headers)));\n        $stream->addStream($body);\n        $stream->addStream(Utils::streamFor(\"\\r\\n\"));\n    }\n\n    private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers): array\n    {\n        // Set a default content-disposition header if one was no provided\n        $disposition = $this->getHeader($headers, 'content-disposition');\n        if (!$disposition) {\n            $headers['Content-Disposition'] = ($filename === '0' || $filename)\n                ? sprintf(\n                    'form-data; name=\"%s\"; filename=\"%s\"',\n                    $name,\n                    basename($filename)\n                )\n                : \"form-data; name=\\\"{$name}\\\"\";\n        }\n\n        // Set a default content-length header if one was no provided\n        $length = $this->getHeader($headers, 'content-length');\n        if (!$length) {\n            if ($length = $stream->getSize()) {\n                $headers['Content-Length'] = (string) $length;\n            }\n        }\n\n        // Set a default Content-Type if one was not supplied\n        $type = $this->getHeader($headers, 'content-type');\n        if (!$type && ($filename === '0' || $filename)) {\n            if ($type = MimeType::fromFilename($filename)) {\n                $headers['Content-Type'] = $type;\n            }\n        }\n\n        return [$stream, $headers];\n    }\n\n    private function getHeader(array $headers, string $key)\n    {\n        $lowercaseHeader = strtolower($key);\n        foreach ($headers as $k => $v) {\n            if (strtolower($k) === $lowercaseHeader) {\n                return $v;\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/NoSeekStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Stream decorator that prevents a stream from being seeked.\n */\nfinal class NoSeekStream implements StreamInterface\n{\n    use StreamDecoratorTrait;\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        throw new \\RuntimeException('Cannot seek a NoSeekStream');\n    }\n\n    public function isSeekable(): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/PumpStream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Provides a read only stream that pumps data from a PHP callable.\n *\n * When invoking the provided callable, the PumpStream will pass the amount of\n * data requested to read to the callable. The callable can choose to ignore\n * this value and return fewer or more bytes than requested. Any extra data\n * returned by the provided callable is buffered internally until drained using\n * the read() function of the PumpStream. The provided callable MUST return\n * false when there is no more data to read.\n */\nfinal class PumpStream implements StreamInterface\n{\n    /** @var callable|null */\n    private $source;\n\n    /** @var int|null */\n    private $size;\n\n    /** @var int */\n    private $tellPos = 0;\n\n    /** @var array */\n    private $metadata;\n\n    /** @var BufferStream */\n    private $buffer;\n\n    /**\n     * @param callable(int): (string|null|false)  $source  Source of the stream data. The callable MAY\n     *                                                     accept an integer argument used to control the\n     *                                                     amount of data to return. The callable MUST\n     *                                                     return a string when called, or false|null on error\n     *                                                     or EOF.\n     * @param array{size?: int, metadata?: array} $options Stream options:\n     *                                                     - metadata: Hash of metadata to use with stream.\n     *                                                     - size: Size of the stream, if known.\n     */\n    public function __construct(callable $source, array $options = [])\n    {\n        $this->source = $source;\n        $this->size = $options['size'] ?? null;\n        $this->metadata = $options['metadata'] ?? [];\n        $this->buffer = new BufferStream();\n    }\n\n    public function __toString(): string\n    {\n        try {\n            return Utils::copyToString($this);\n        } catch (\\Throwable $e) {\n            if (\\PHP_VERSION_ID >= 70400) {\n                throw $e;\n            }\n            trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);\n            return '';\n        }\n    }\n\n    public function close(): void\n    {\n        $this->detach();\n    }\n\n    public function detach()\n    {\n        $this->tellPos = 0;\n        $this->source = null;\n\n        return null;\n    }\n\n    public function getSize(): ?int\n    {\n        return $this->size;\n    }\n\n    public function tell(): int\n    {\n        return $this->tellPos;\n    }\n\n    public function eof(): bool\n    {\n        return $this->source === null;\n    }\n\n    public function isSeekable(): bool\n    {\n        return false;\n    }\n\n    public function rewind(): void\n    {\n        $this->seek(0);\n    }\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        throw new \\RuntimeException('Cannot seek a PumpStream');\n    }\n\n    public function isWritable(): bool\n    {\n        return false;\n    }\n\n    public function write($string): int\n    {\n        throw new \\RuntimeException('Cannot write to a PumpStream');\n    }\n\n    public function isReadable(): bool\n    {\n        return true;\n    }\n\n    public function read($length): string\n    {\n        $data = $this->buffer->read($length);\n        $readLen = strlen($data);\n        $this->tellPos += $readLen;\n        $remaining = $length - $readLen;\n\n        if ($remaining) {\n            $this->pump($remaining);\n            $data .= $this->buffer->read($remaining);\n            $this->tellPos += strlen($data) - $readLen;\n        }\n\n        return $data;\n    }\n\n    public function getContents(): string\n    {\n        $result = '';\n        while (!$this->eof()) {\n            $result .= $this->read(1000000);\n        }\n\n        return $result;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getMetadata($key = null)\n    {\n        if (!$key) {\n            return $this->metadata;\n        }\n\n        return $this->metadata[$key] ?? null;\n    }\n\n    private function pump(int $length): void\n    {\n        if ($this->source) {\n            do {\n                $data = call_user_func($this->source, $length);\n                if ($data === false || $data === null) {\n                    $this->source = null;\n                    return;\n                }\n                $this->buffer->write($data);\n                $length -= strlen($data);\n            } while ($length > 0);\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Query.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nfinal class Query\n{\n    /**\n     * Parse a query string into an associative array.\n     *\n     * If multiple values are found for the same key, the value of that key\n     * value pair will become an array. This function does not parse nested\n     * PHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2`\n     * will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`.\n     *\n     * @param string   $str         Query string to parse\n     * @param int|bool $urlEncoding How the query string is encoded\n     */\n    public static function parse(string $str, $urlEncoding = true): array\n    {\n        $result = [];\n\n        if ($str === '') {\n            return $result;\n        }\n\n        if ($urlEncoding === true) {\n            $decoder = function ($value) {\n                return rawurldecode(str_replace('+', ' ', (string) $value));\n            };\n        } elseif ($urlEncoding === PHP_QUERY_RFC3986) {\n            $decoder = 'rawurldecode';\n        } elseif ($urlEncoding === PHP_QUERY_RFC1738) {\n            $decoder = 'urldecode';\n        } else {\n            $decoder = function ($str) {\n                return $str;\n            };\n        }\n\n        foreach (explode('&', $str) as $kvp) {\n            $parts = explode('=', $kvp, 2);\n            $key = $decoder($parts[0]);\n            $value = isset($parts[1]) ? $decoder($parts[1]) : null;\n            if (!isset($result[$key])) {\n                $result[$key] = $value;\n            } else {\n                if (!is_array($result[$key])) {\n                    $result[$key] = [$result[$key]];\n                }\n                $result[$key][] = $value;\n            }\n        }\n\n        return $result;\n    }\n\n    /**\n     * Build a query string from an array of key value pairs.\n     *\n     * This function can use the return value of `parse()` to build a query\n     * string. This function does not modify the provided keys when an array is\n     * encountered (like `http_build_query()` would).\n     *\n     * @param array     $params   Query string parameters.\n     * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986\n     *                            to encode using RFC3986, or PHP_QUERY_RFC1738\n     *                            to encode using RFC1738.\n     */\n    public static function build(array $params, $encoding = PHP_QUERY_RFC3986): string\n    {\n        if (!$params) {\n            return '';\n        }\n\n        if ($encoding === false) {\n            $encoder = function (string $str): string {\n                return $str;\n            };\n        } elseif ($encoding === PHP_QUERY_RFC3986) {\n            $encoder = 'rawurlencode';\n        } elseif ($encoding === PHP_QUERY_RFC1738) {\n            $encoder = 'urlencode';\n        } else {\n            throw new \\InvalidArgumentException('Invalid type');\n        }\n\n        $qs = '';\n        foreach ($params as $k => $v) {\n            $k = $encoder((string) $k);\n            if (!is_array($v)) {\n                $qs .= $k;\n                $v = is_bool($v) ? (int) $v : $v;\n                if ($v !== null) {\n                    $qs .= '=' . $encoder((string) $v);\n                }\n                $qs .= '&';\n            } else {\n                foreach ($v as $vv) {\n                    $qs .= $k;\n                    $vv = is_bool($vv) ? (int) $vv : $vv;\n                    if ($vv !== null) {\n                        $qs .= '=' . $encoder((string) $vv);\n                    }\n                    $qs .= '&';\n                }\n            }\n        }\n\n        return $qs ? (string) substr($qs, 0, -1) : '';\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Request.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse InvalidArgumentException;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\StreamInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * PSR-7 request implementation.\n */\nclass Request implements RequestInterface\n{\n    use MessageTrait;\n\n    /** @var string */\n    private $method;\n\n    /** @var string|null */\n    private $requestTarget;\n\n    /** @var UriInterface */\n    private $uri;\n\n    /**\n     * @param string                               $method  HTTP method\n     * @param string|UriInterface                  $uri     URI\n     * @param array<string, string|string[]>       $headers Request headers\n     * @param string|resource|StreamInterface|null $body    Request body\n     * @param string                               $version Protocol version\n     */\n    public function __construct(\n        string $method,\n        $uri,\n        array $headers = [],\n        $body = null,\n        string $version = '1.1'\n    ) {\n        $this->assertMethod($method);\n        if (!($uri instanceof UriInterface)) {\n            $uri = new Uri($uri);\n        }\n\n        $this->method = strtoupper($method);\n        $this->uri = $uri;\n        $this->setHeaders($headers);\n        $this->protocol = $version;\n\n        if (!isset($this->headerNames['host'])) {\n            $this->updateHostFromUri();\n        }\n\n        if ($body !== '' && $body !== null) {\n            $this->stream = Utils::streamFor($body);\n        }\n    }\n\n    public function getRequestTarget(): string\n    {\n        if ($this->requestTarget !== null) {\n            return $this->requestTarget;\n        }\n\n        $target = $this->uri->getPath();\n        if ($target === '') {\n            $target = '/';\n        }\n        if ($this->uri->getQuery() != '') {\n            $target .= '?' . $this->uri->getQuery();\n        }\n\n        return $target;\n    }\n\n    public function withRequestTarget($requestTarget): RequestInterface\n    {\n        if (preg_match('#\\s#', $requestTarget)) {\n            throw new InvalidArgumentException(\n                'Invalid request target provided; cannot contain whitespace'\n            );\n        }\n\n        $new = clone $this;\n        $new->requestTarget = $requestTarget;\n        return $new;\n    }\n\n    public function getMethod(): string\n    {\n        return $this->method;\n    }\n\n    public function withMethod($method): RequestInterface\n    {\n        $this->assertMethod($method);\n        $new = clone $this;\n        $new->method = strtoupper($method);\n        return $new;\n    }\n\n    public function getUri(): UriInterface\n    {\n        return $this->uri;\n    }\n\n    public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface\n    {\n        if ($uri === $this->uri) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->uri = $uri;\n\n        if (!$preserveHost || !isset($this->headerNames['host'])) {\n            $new->updateHostFromUri();\n        }\n\n        return $new;\n    }\n\n    private function updateHostFromUri(): void\n    {\n        $host = $this->uri->getHost();\n\n        if ($host == '') {\n            return;\n        }\n\n        if (($port = $this->uri->getPort()) !== null) {\n            $host .= ':' . $port;\n        }\n\n        if (isset($this->headerNames['host'])) {\n            $header = $this->headerNames['host'];\n        } else {\n            $header = 'Host';\n            $this->headerNames['host'] = 'Host';\n        }\n        // Ensure Host is the first header.\n        // See: http://tools.ietf.org/html/rfc7230#section-5.4\n        $this->headers = [$header => [$host]] + $this->headers;\n    }\n\n    /**\n     * @param mixed $method\n     */\n    private function assertMethod($method): void\n    {\n        if (!is_string($method) || $method === '') {\n            throw new InvalidArgumentException('Method must be a non-empty string.');\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Response.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * PSR-7 response implementation.\n */\nclass Response implements ResponseInterface\n{\n    use MessageTrait;\n\n    /** Map of standard HTTP status code/reason phrases */\n    private const PHRASES = [\n        100 => 'Continue',\n        101 => 'Switching Protocols',\n        102 => 'Processing',\n        200 => 'OK',\n        201 => 'Created',\n        202 => 'Accepted',\n        203 => 'Non-Authoritative Information',\n        204 => 'No Content',\n        205 => 'Reset Content',\n        206 => 'Partial Content',\n        207 => 'Multi-status',\n        208 => 'Already Reported',\n        300 => 'Multiple Choices',\n        301 => 'Moved Permanently',\n        302 => 'Found',\n        303 => 'See Other',\n        304 => 'Not Modified',\n        305 => 'Use Proxy',\n        306 => 'Switch Proxy',\n        307 => 'Temporary Redirect',\n        308 => 'Permanent Redirect',\n        400 => 'Bad Request',\n        401 => 'Unauthorized',\n        402 => 'Payment Required',\n        403 => 'Forbidden',\n        404 => 'Not Found',\n        405 => 'Method Not Allowed',\n        406 => 'Not Acceptable',\n        407 => 'Proxy Authentication Required',\n        408 => 'Request Time-out',\n        409 => 'Conflict',\n        410 => 'Gone',\n        411 => 'Length Required',\n        412 => 'Precondition Failed',\n        413 => 'Request Entity Too Large',\n        414 => 'Request-URI Too Large',\n        415 => 'Unsupported Media Type',\n        416 => 'Requested range not satisfiable',\n        417 => 'Expectation Failed',\n        418 => 'I\\'m a teapot',\n        422 => 'Unprocessable Entity',\n        423 => 'Locked',\n        424 => 'Failed Dependency',\n        425 => 'Unordered Collection',\n        426 => 'Upgrade Required',\n        428 => 'Precondition Required',\n        429 => 'Too Many Requests',\n        431 => 'Request Header Fields Too Large',\n        451 => 'Unavailable For Legal Reasons',\n        500 => 'Internal Server Error',\n        501 => 'Not Implemented',\n        502 => 'Bad Gateway',\n        503 => 'Service Unavailable',\n        504 => 'Gateway Time-out',\n        505 => 'HTTP Version not supported',\n        506 => 'Variant Also Negotiates',\n        507 => 'Insufficient Storage',\n        508 => 'Loop Detected',\n        510 => 'Not Extended',\n        511 => 'Network Authentication Required',\n    ];\n\n    /** @var string */\n    private $reasonPhrase;\n\n    /** @var int */\n    private $statusCode;\n\n    /**\n     * @param int                                  $status  Status code\n     * @param array<string, string|string[]>       $headers Response headers\n     * @param string|resource|StreamInterface|null $body    Response body\n     * @param string                               $version Protocol version\n     * @param string|null                          $reason  Reason phrase (when empty a default will be used based on the status code)\n     */\n    public function __construct(\n        int $status = 200,\n        array $headers = [],\n        $body = null,\n        string $version = '1.1',\n        string $reason = null\n    ) {\n        $this->assertStatusCodeRange($status);\n\n        $this->statusCode = $status;\n\n        if ($body !== '' && $body !== null) {\n            $this->stream = Utils::streamFor($body);\n        }\n\n        $this->setHeaders($headers);\n        if ($reason == '' && isset(self::PHRASES[$this->statusCode])) {\n            $this->reasonPhrase = self::PHRASES[$this->statusCode];\n        } else {\n            $this->reasonPhrase = (string) $reason;\n        }\n\n        $this->protocol = $version;\n    }\n\n    public function getStatusCode(): int\n    {\n        return $this->statusCode;\n    }\n\n    public function getReasonPhrase(): string\n    {\n        return $this->reasonPhrase;\n    }\n\n    public function withStatus($code, $reasonPhrase = ''): ResponseInterface\n    {\n        $this->assertStatusCodeIsInteger($code);\n        $code = (int) $code;\n        $this->assertStatusCodeRange($code);\n\n        $new = clone $this;\n        $new->statusCode = $code;\n        if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) {\n            $reasonPhrase = self::PHRASES[$new->statusCode];\n        }\n        $new->reasonPhrase = (string) $reasonPhrase;\n        return $new;\n    }\n\n    /**\n     * @param mixed $statusCode\n     */\n    private function assertStatusCodeIsInteger($statusCode): void\n    {\n        if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) {\n            throw new \\InvalidArgumentException('Status code must be an integer value.');\n        }\n    }\n\n    private function assertStatusCodeRange(int $statusCode): void\n    {\n        if ($statusCode < 100 || $statusCode >= 600) {\n            throw new \\InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.');\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Rfc7230.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\n/**\n * @internal\n */\nfinal class Rfc7230\n{\n    /**\n     * Header related regular expressions (based on amphp/http package)\n     *\n     * Note: header delimiter (\\r\\n) is modified to \\r?\\n to accept line feed only delimiters for BC reasons.\n     *\n     * @link    https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15\n     *\n     * @license https://github.com/amphp/http/blob/v1.0.1/LICENSE\n     */\n    public const HEADER_REGEX = \"(^([^()<>@,;:\\\\\\\"/[\\]?={}\\x01-\\x20\\x7F]++):[ \\t]*+((?:[ \\t]*+[\\x21-\\x7E\\x80-\\xFF]++)*+)[ \\t]*+\\r?\\n)m\";\n    public const HEADER_FOLD_REGEX = \"(\\r?\\n[ \\t]++)\";\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/ServerRequest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse InvalidArgumentException;\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Message\\StreamInterface;\nuse Psr\\Http\\Message\\UploadedFileInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Server-side HTTP request\n *\n * Extends the Request definition to add methods for accessing incoming data,\n * specifically server parameters, cookies, matched path parameters, query\n * string arguments, body parameters, and upload file information.\n *\n * \"Attributes\" are discovered via decomposing the request (and usually\n * specifically the URI path), and typically will be injected by the application.\n *\n * Requests are considered immutable; all methods that might change state are\n * implemented such that they retain the internal state of the current\n * message and return a new instance that contains the changed state.\n */\nclass ServerRequest extends Request implements ServerRequestInterface\n{\n    /**\n     * @var array\n     */\n    private $attributes = [];\n\n    /**\n     * @var array\n     */\n    private $cookieParams = [];\n\n    /**\n     * @var array|object|null\n     */\n    private $parsedBody;\n\n    /**\n     * @var array\n     */\n    private $queryParams = [];\n\n    /**\n     * @var array\n     */\n    private $serverParams;\n\n    /**\n     * @var array\n     */\n    private $uploadedFiles = [];\n\n    /**\n     * @param string                               $method       HTTP method\n     * @param string|UriInterface                  $uri          URI\n     * @param array<string, string|string[]>       $headers      Request headers\n     * @param string|resource|StreamInterface|null $body         Request body\n     * @param string                               $version      Protocol version\n     * @param array                                $serverParams Typically the $_SERVER superglobal\n     */\n    public function __construct(\n        string $method,\n        $uri,\n        array $headers = [],\n        $body = null,\n        string $version = '1.1',\n        array $serverParams = []\n    ) {\n        $this->serverParams = $serverParams;\n\n        parent::__construct($method, $uri, $headers, $body, $version);\n    }\n\n    /**\n     * Return an UploadedFile instance array.\n     *\n     * @param array $files A array which respect $_FILES structure\n     *\n     * @throws InvalidArgumentException for unrecognized values\n     */\n    public static function normalizeFiles(array $files): array\n    {\n        $normalized = [];\n\n        foreach ($files as $key => $value) {\n            if ($value instanceof UploadedFileInterface) {\n                $normalized[$key] = $value;\n            } elseif (is_array($value) && isset($value['tmp_name'])) {\n                $normalized[$key] = self::createUploadedFileFromSpec($value);\n            } elseif (is_array($value)) {\n                $normalized[$key] = self::normalizeFiles($value);\n                continue;\n            } else {\n                throw new InvalidArgumentException('Invalid value in files specification');\n            }\n        }\n\n        return $normalized;\n    }\n\n    /**\n     * Create and return an UploadedFile instance from a $_FILES specification.\n     *\n     * If the specification represents an array of values, this method will\n     * delegate to normalizeNestedFileSpec() and return that return value.\n     *\n     * @param array $value $_FILES struct\n     *\n     * @return UploadedFileInterface|UploadedFileInterface[]\n     */\n    private static function createUploadedFileFromSpec(array $value)\n    {\n        if (is_array($value['tmp_name'])) {\n            return self::normalizeNestedFileSpec($value);\n        }\n\n        return new UploadedFile(\n            $value['tmp_name'],\n            (int) $value['size'],\n            (int) $value['error'],\n            $value['name'],\n            $value['type']\n        );\n    }\n\n    /**\n     * Normalize an array of file specifications.\n     *\n     * Loops through all nested files and returns a normalized array of\n     * UploadedFileInterface instances.\n     *\n     * @return UploadedFileInterface[]\n     */\n    private static function normalizeNestedFileSpec(array $files = []): array\n    {\n        $normalizedFiles = [];\n\n        foreach (array_keys($files['tmp_name']) as $key) {\n            $spec = [\n                'tmp_name' => $files['tmp_name'][$key],\n                'size'     => $files['size'][$key],\n                'error'    => $files['error'][$key],\n                'name'     => $files['name'][$key],\n                'type'     => $files['type'][$key],\n            ];\n            $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);\n        }\n\n        return $normalizedFiles;\n    }\n\n    /**\n     * Return a ServerRequest populated with superglobals:\n     * $_GET\n     * $_POST\n     * $_COOKIE\n     * $_FILES\n     * $_SERVER\n     */\n    public static function fromGlobals(): ServerRequestInterface\n    {\n        $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';\n        $headers = getallheaders();\n        $uri = self::getUriFromGlobals();\n        $body = new CachingStream(new LazyOpenStream('php://input', 'r+'));\n        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';\n\n        $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);\n\n        return $serverRequest\n            ->withCookieParams($_COOKIE)\n            ->withQueryParams($_GET)\n            ->withParsedBody($_POST)\n            ->withUploadedFiles(self::normalizeFiles($_FILES));\n    }\n\n    private static function extractHostAndPortFromAuthority(string $authority): array\n    {\n        $uri = 'http://' . $authority;\n        $parts = parse_url($uri);\n        if (false === $parts) {\n            return [null, null];\n        }\n\n        $host = $parts['host'] ?? null;\n        $port = $parts['port'] ?? null;\n\n        return [$host, $port];\n    }\n\n    /**\n     * Get a Uri populated with values from $_SERVER.\n     */\n    public static function getUriFromGlobals(): UriInterface\n    {\n        $uri = new Uri('');\n\n        $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');\n\n        $hasPort = false;\n        if (isset($_SERVER['HTTP_HOST'])) {\n            [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);\n            if ($host !== null) {\n                $uri = $uri->withHost($host);\n            }\n\n            if ($port !== null) {\n                $hasPort = true;\n                $uri = $uri->withPort($port);\n            }\n        } elseif (isset($_SERVER['SERVER_NAME'])) {\n            $uri = $uri->withHost($_SERVER['SERVER_NAME']);\n        } elseif (isset($_SERVER['SERVER_ADDR'])) {\n            $uri = $uri->withHost($_SERVER['SERVER_ADDR']);\n        }\n\n        if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {\n            $uri = $uri->withPort($_SERVER['SERVER_PORT']);\n        }\n\n        $hasQuery = false;\n        if (isset($_SERVER['REQUEST_URI'])) {\n            $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2);\n            $uri = $uri->withPath($requestUriParts[0]);\n            if (isset($requestUriParts[1])) {\n                $hasQuery = true;\n                $uri = $uri->withQuery($requestUriParts[1]);\n            }\n        }\n\n        if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {\n            $uri = $uri->withQuery($_SERVER['QUERY_STRING']);\n        }\n\n        return $uri;\n    }\n\n    public function getServerParams(): array\n    {\n        return $this->serverParams;\n    }\n\n    public function getUploadedFiles(): array\n    {\n        return $this->uploadedFiles;\n    }\n\n    public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface\n    {\n        $new = clone $this;\n        $new->uploadedFiles = $uploadedFiles;\n\n        return $new;\n    }\n\n    public function getCookieParams(): array\n    {\n        return $this->cookieParams;\n    }\n\n    public function withCookieParams(array $cookies): ServerRequestInterface\n    {\n        $new = clone $this;\n        $new->cookieParams = $cookies;\n\n        return $new;\n    }\n\n    public function getQueryParams(): array\n    {\n        return $this->queryParams;\n    }\n\n    public function withQueryParams(array $query): ServerRequestInterface\n    {\n        $new = clone $this;\n        $new->queryParams = $query;\n\n        return $new;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return array|object|null\n     */\n    public function getParsedBody()\n    {\n        return $this->parsedBody;\n    }\n\n    public function withParsedBody($data): ServerRequestInterface\n    {\n        $new = clone $this;\n        $new->parsedBody = $data;\n\n        return $new;\n    }\n\n    public function getAttributes(): array\n    {\n        return $this->attributes;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getAttribute($attribute, $default = null)\n    {\n        if (false === array_key_exists($attribute, $this->attributes)) {\n            return $default;\n        }\n\n        return $this->attributes[$attribute];\n    }\n\n    public function withAttribute($attribute, $value): ServerRequestInterface\n    {\n        $new = clone $this;\n        $new->attributes[$attribute] = $value;\n\n        return $new;\n    }\n\n    public function withoutAttribute($attribute): ServerRequestInterface\n    {\n        if (false === array_key_exists($attribute, $this->attributes)) {\n            return $this;\n        }\n\n        $new = clone $this;\n        unset($new->attributes[$attribute]);\n\n        return $new;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Stream.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * PHP stream implementation.\n */\nclass Stream implements StreamInterface\n{\n    /**\n     * @see http://php.net/manual/function.fopen.php\n     * @see http://php.net/manual/en/function.gzopen.php\n     */\n    private const READABLE_MODES = '/r|a\\+|ab\\+|w\\+|wb\\+|x\\+|xb\\+|c\\+|cb\\+/';\n    private const WRITABLE_MODES = '/a|w|r\\+|rb\\+|rw|x|c/';\n\n    /** @var resource */\n    private $stream;\n    /** @var int|null */\n    private $size;\n    /** @var bool */\n    private $seekable;\n    /** @var bool */\n    private $readable;\n    /** @var bool */\n    private $writable;\n    /** @var string|null */\n    private $uri;\n    /** @var mixed[] */\n    private $customMetadata;\n\n    /**\n     * This constructor accepts an associative array of options.\n     *\n     * - size: (int) If a read stream would otherwise have an indeterminate\n     *   size, but the size is known due to foreknowledge, then you can\n     *   provide that size, in bytes.\n     * - metadata: (array) Any additional metadata to return when the metadata\n     *   of the stream is accessed.\n     *\n     * @param resource                            $stream  Stream resource to wrap.\n     * @param array{size?: int, metadata?: array} $options Associative array of options.\n     *\n     * @throws \\InvalidArgumentException if the stream is not a stream resource\n     */\n    public function __construct($stream, array $options = [])\n    {\n        if (!is_resource($stream)) {\n            throw new \\InvalidArgumentException('Stream must be a resource');\n        }\n\n        if (isset($options['size'])) {\n            $this->size = $options['size'];\n        }\n\n        $this->customMetadata = $options['metadata'] ?? [];\n        $this->stream = $stream;\n        $meta = stream_get_meta_data($this->stream);\n        $this->seekable = $meta['seekable'];\n        $this->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']);\n        $this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta['mode']);\n        $this->uri = $this->getMetadata('uri');\n    }\n\n    /**\n     * Closes the stream when the destructed\n     */\n    public function __destruct()\n    {\n        $this->close();\n    }\n\n    public function __toString(): string\n    {\n        try {\n            if ($this->isSeekable()) {\n                $this->seek(0);\n            }\n            return $this->getContents();\n        } catch (\\Throwable $e) {\n            if (\\PHP_VERSION_ID >= 70400) {\n                throw $e;\n            }\n            trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);\n            return '';\n        }\n    }\n\n    public function getContents(): string\n    {\n        if (!isset($this->stream)) {\n            throw new \\RuntimeException('Stream is detached');\n        }\n\n        $contents = stream_get_contents($this->stream);\n\n        if ($contents === false) {\n            throw new \\RuntimeException('Unable to read stream contents');\n        }\n\n        return $contents;\n    }\n\n    public function close(): void\n    {\n        if (isset($this->stream)) {\n            if (is_resource($this->stream)) {\n                fclose($this->stream);\n            }\n            $this->detach();\n        }\n    }\n\n    public function detach()\n    {\n        if (!isset($this->stream)) {\n            return null;\n        }\n\n        $result = $this->stream;\n        unset($this->stream);\n        $this->size = $this->uri = null;\n        $this->readable = $this->writable = $this->seekable = false;\n\n        return $result;\n    }\n\n    public function getSize(): ?int\n    {\n        if ($this->size !== null) {\n            return $this->size;\n        }\n\n        if (!isset($this->stream)) {\n            return null;\n        }\n\n        // Clear the stat cache if the stream has a URI\n        if ($this->uri) {\n            clearstatcache(true, $this->uri);\n        }\n\n        $stats = fstat($this->stream);\n        if (is_array($stats) && isset($stats['size'])) {\n            $this->size = $stats['size'];\n            return $this->size;\n        }\n\n        return null;\n    }\n\n    public function isReadable(): bool\n    {\n        return $this->readable;\n    }\n\n    public function isWritable(): bool\n    {\n        return $this->writable;\n    }\n\n    public function isSeekable(): bool\n    {\n        return $this->seekable;\n    }\n\n    public function eof(): bool\n    {\n        if (!isset($this->stream)) {\n            throw new \\RuntimeException('Stream is detached');\n        }\n\n        return feof($this->stream);\n    }\n\n    public function tell(): int\n    {\n        if (!isset($this->stream)) {\n            throw new \\RuntimeException('Stream is detached');\n        }\n\n        $result = ftell($this->stream);\n\n        if ($result === false) {\n            throw new \\RuntimeException('Unable to determine stream position');\n        }\n\n        return $result;\n    }\n\n    public function rewind(): void\n    {\n        $this->seek(0);\n    }\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        $whence = (int) $whence;\n\n        if (!isset($this->stream)) {\n            throw new \\RuntimeException('Stream is detached');\n        }\n        if (!$this->seekable) {\n            throw new \\RuntimeException('Stream is not seekable');\n        }\n        if (fseek($this->stream, $offset, $whence) === -1) {\n            throw new \\RuntimeException('Unable to seek to stream position '\n                . $offset . ' with whence ' . var_export($whence, true));\n        }\n    }\n\n    public function read($length): string\n    {\n        if (!isset($this->stream)) {\n            throw new \\RuntimeException('Stream is detached');\n        }\n        if (!$this->readable) {\n            throw new \\RuntimeException('Cannot read from non-readable stream');\n        }\n        if ($length < 0) {\n            throw new \\RuntimeException('Length parameter cannot be negative');\n        }\n\n        if (0 === $length) {\n            return '';\n        }\n\n        $string = fread($this->stream, $length);\n        if (false === $string) {\n            throw new \\RuntimeException('Unable to read from stream');\n        }\n\n        return $string;\n    }\n\n    public function write($string): int\n    {\n        if (!isset($this->stream)) {\n            throw new \\RuntimeException('Stream is detached');\n        }\n        if (!$this->writable) {\n            throw new \\RuntimeException('Cannot write to a non-writable stream');\n        }\n\n        // We can't know the size after writing anything\n        $this->size = null;\n        $result = fwrite($this->stream, $string);\n\n        if ($result === false) {\n            throw new \\RuntimeException('Unable to write to stream');\n        }\n\n        return $result;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getMetadata($key = null)\n    {\n        if (!isset($this->stream)) {\n            return $key ? null : [];\n        } elseif (!$key) {\n            return $this->customMetadata + stream_get_meta_data($this->stream);\n        } elseif (isset($this->customMetadata[$key])) {\n            return $this->customMetadata[$key];\n        }\n\n        $meta = stream_get_meta_data($this->stream);\n\n        return $meta[$key] ?? null;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Stream decorator trait\n *\n * @property StreamInterface $stream\n */\ntrait StreamDecoratorTrait\n{\n    /**\n     * @param StreamInterface $stream Stream to decorate\n     */\n    public function __construct(StreamInterface $stream)\n    {\n        $this->stream = $stream;\n    }\n\n    /**\n     * Magic method used to create a new stream if streams are not added in\n     * the constructor of a decorator (e.g., LazyOpenStream).\n     *\n     * @return StreamInterface\n     */\n    public function __get(string $name)\n    {\n        if ($name === 'stream') {\n            $this->stream = $this->createStream();\n            return $this->stream;\n        }\n\n        throw new \\UnexpectedValueException(\"$name not found on class\");\n    }\n\n    public function __toString(): string\n    {\n        try {\n            if ($this->isSeekable()) {\n                $this->seek(0);\n            }\n            return $this->getContents();\n        } catch (\\Throwable $e) {\n            if (\\PHP_VERSION_ID >= 70400) {\n                throw $e;\n            }\n            trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);\n            return '';\n        }\n    }\n\n    public function getContents(): string\n    {\n        return Utils::copyToString($this);\n    }\n\n    /**\n     * Allow decorators to implement custom methods\n     *\n     * @return mixed\n     */\n    public function __call(string $method, array $args)\n    {\n        /** @var callable $callable */\n        $callable = [$this->stream, $method];\n        $result = call_user_func_array($callable, $args);\n\n        // Always return the wrapped object if the result is a return $this\n        return $result === $this->stream ? $this : $result;\n    }\n\n    public function close(): void\n    {\n        $this->stream->close();\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return mixed\n     */\n    public function getMetadata($key = null)\n    {\n        return $this->stream->getMetadata($key);\n    }\n\n    public function detach()\n    {\n        return $this->stream->detach();\n    }\n\n    public function getSize(): ?int\n    {\n        return $this->stream->getSize();\n    }\n\n    public function eof(): bool\n    {\n        return $this->stream->eof();\n    }\n\n    public function tell(): int\n    {\n        return $this->stream->tell();\n    }\n\n    public function isReadable(): bool\n    {\n        return $this->stream->isReadable();\n    }\n\n    public function isWritable(): bool\n    {\n        return $this->stream->isWritable();\n    }\n\n    public function isSeekable(): bool\n    {\n        return $this->stream->isSeekable();\n    }\n\n    public function rewind(): void\n    {\n        $this->seek(0);\n    }\n\n    public function seek($offset, $whence = SEEK_SET): void\n    {\n        $this->stream->seek($offset, $whence);\n    }\n\n    public function read($length): string\n    {\n        return $this->stream->read($length);\n    }\n\n    public function write($string): int\n    {\n        return $this->stream->write($string);\n    }\n\n    /**\n     * Implement in subclasses to dynamically create streams when requested.\n     *\n     * @throws \\BadMethodCallException\n     */\n    protected function createStream(): StreamInterface\n    {\n        throw new \\BadMethodCallException('Not implemented');\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/StreamWrapper.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\StreamInterface;\n\n/**\n * Converts Guzzle streams into PHP stream resources.\n *\n * @see https://www.php.net/streamwrapper\n */\nfinal class StreamWrapper\n{\n    /** @var resource */\n    public $context;\n\n    /** @var StreamInterface */\n    private $stream;\n\n    /** @var string r, r+, or w */\n    private $mode;\n\n    /**\n     * Returns a resource representing the stream.\n     *\n     * @param StreamInterface $stream The stream to get a resource for\n     *\n     * @return resource\n     *\n     * @throws \\InvalidArgumentException if stream is not readable or writable\n     */\n    public static function getResource(StreamInterface $stream)\n    {\n        self::register();\n\n        if ($stream->isReadable()) {\n            $mode = $stream->isWritable() ? 'r+' : 'r';\n        } elseif ($stream->isWritable()) {\n            $mode = 'w';\n        } else {\n            throw new \\InvalidArgumentException('The stream must be readable, '\n                . 'writable, or both.');\n        }\n\n        return fopen('guzzle://stream', $mode, false, self::createStreamContext($stream));\n    }\n\n    /**\n     * Creates a stream context that can be used to open a stream as a php stream resource.\n     *\n     * @return resource\n     */\n    public static function createStreamContext(StreamInterface $stream)\n    {\n        return stream_context_create([\n            'guzzle' => ['stream' => $stream]\n        ]);\n    }\n\n    /**\n     * Registers the stream wrapper if needed\n     */\n    public static function register(): void\n    {\n        if (!in_array('guzzle', stream_get_wrappers())) {\n            stream_wrapper_register('guzzle', __CLASS__);\n        }\n    }\n\n    public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool\n    {\n        $options = stream_context_get_options($this->context);\n\n        if (!isset($options['guzzle']['stream'])) {\n            return false;\n        }\n\n        $this->mode = $mode;\n        $this->stream = $options['guzzle']['stream'];\n\n        return true;\n    }\n\n    public function stream_read(int $count): string\n    {\n        return $this->stream->read($count);\n    }\n\n    public function stream_write(string $data): int\n    {\n        return $this->stream->write($data);\n    }\n\n    public function stream_tell(): int\n    {\n        return $this->stream->tell();\n    }\n\n    public function stream_eof(): bool\n    {\n        return $this->stream->eof();\n    }\n\n    public function stream_seek(int $offset, int $whence): bool\n    {\n        $this->stream->seek($offset, $whence);\n\n        return true;\n    }\n\n    /**\n     * @return resource|false\n     */\n    public function stream_cast(int $cast_as)\n    {\n        $stream = clone($this->stream);\n        $resource = $stream->detach();\n\n        return $resource ?? false;\n    }\n\n    /**\n     * @return array<int|string, int>\n     */\n    public function stream_stat(): array\n    {\n        static $modeMap = [\n            'r'  => 33060,\n            'rb' => 33060,\n            'r+' => 33206,\n            'w'  => 33188,\n            'wb' => 33188\n        ];\n\n        return [\n            'dev'     => 0,\n            'ino'     => 0,\n            'mode'    => $modeMap[$this->mode],\n            'nlink'   => 0,\n            'uid'     => 0,\n            'gid'     => 0,\n            'rdev'    => 0,\n            'size'    => $this->stream->getSize() ?: 0,\n            'atime'   => 0,\n            'mtime'   => 0,\n            'ctime'   => 0,\n            'blksize' => 0,\n            'blocks'  => 0\n        ];\n    }\n\n    /**\n     * @return array<int|string, int>\n     */\n    public function url_stat(string $path, int $flags): array\n    {\n        return [\n            'dev'     => 0,\n            'ino'     => 0,\n            'mode'    => 0,\n            'nlink'   => 0,\n            'uid'     => 0,\n            'gid'     => 0,\n            'rdev'    => 0,\n            'size'    => 0,\n            'atime'   => 0,\n            'mtime'   => 0,\n            'ctime'   => 0,\n            'blksize' => 0,\n            'blocks'  => 0\n        ];\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/UploadedFile.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse InvalidArgumentException;\nuse Psr\\Http\\Message\\StreamInterface;\nuse Psr\\Http\\Message\\UploadedFileInterface;\nuse RuntimeException;\n\nclass UploadedFile implements UploadedFileInterface\n{\n    private const ERRORS = [\n        UPLOAD_ERR_OK,\n        UPLOAD_ERR_INI_SIZE,\n        UPLOAD_ERR_FORM_SIZE,\n        UPLOAD_ERR_PARTIAL,\n        UPLOAD_ERR_NO_FILE,\n        UPLOAD_ERR_NO_TMP_DIR,\n        UPLOAD_ERR_CANT_WRITE,\n        UPLOAD_ERR_EXTENSION,\n    ];\n\n    /**\n     * @var string|null\n     */\n    private $clientFilename;\n\n    /**\n     * @var string|null\n     */\n    private $clientMediaType;\n\n    /**\n     * @var int\n     */\n    private $error;\n\n    /**\n     * @var string|null\n     */\n    private $file;\n\n    /**\n     * @var bool\n     */\n    private $moved = false;\n\n    /**\n     * @var int|null\n     */\n    private $size;\n\n    /**\n     * @var StreamInterface|null\n     */\n    private $stream;\n\n    /**\n     * @param StreamInterface|string|resource $streamOrFile\n     */\n    public function __construct(\n        $streamOrFile,\n        ?int $size,\n        int $errorStatus,\n        string $clientFilename = null,\n        string $clientMediaType = null\n    ) {\n        $this->setError($errorStatus);\n        $this->size = $size;\n        $this->clientFilename = $clientFilename;\n        $this->clientMediaType = $clientMediaType;\n\n        if ($this->isOk()) {\n            $this->setStreamOrFile($streamOrFile);\n        }\n    }\n\n    /**\n     * Depending on the value set file or stream variable\n     *\n     * @param StreamInterface|string|resource $streamOrFile\n     *\n     * @throws InvalidArgumentException\n     */\n    private function setStreamOrFile($streamOrFile): void\n    {\n        if (is_string($streamOrFile)) {\n            $this->file = $streamOrFile;\n        } elseif (is_resource($streamOrFile)) {\n            $this->stream = new Stream($streamOrFile);\n        } elseif ($streamOrFile instanceof StreamInterface) {\n            $this->stream = $streamOrFile;\n        } else {\n            throw new InvalidArgumentException(\n                'Invalid stream or file provided for UploadedFile'\n            );\n        }\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function setError(int $error): void\n    {\n        if (false === in_array($error, UploadedFile::ERRORS, true)) {\n            throw new InvalidArgumentException(\n                'Invalid error status for UploadedFile'\n            );\n        }\n\n        $this->error = $error;\n    }\n\n    private function isStringNotEmpty($param): bool\n    {\n        return is_string($param) && false === empty($param);\n    }\n\n    /**\n     * Return true if there is no upload error\n     */\n    private function isOk(): bool\n    {\n        return $this->error === UPLOAD_ERR_OK;\n    }\n\n    public function isMoved(): bool\n    {\n        return $this->moved;\n    }\n\n    /**\n     * @throws RuntimeException if is moved or not ok\n     */\n    private function validateActive(): void\n    {\n        if (false === $this->isOk()) {\n            throw new RuntimeException('Cannot retrieve stream due to upload error');\n        }\n\n        if ($this->isMoved()) {\n            throw new RuntimeException('Cannot retrieve stream after it has already been moved');\n        }\n    }\n\n    public function getStream(): StreamInterface\n    {\n        $this->validateActive();\n\n        if ($this->stream instanceof StreamInterface) {\n            return $this->stream;\n        }\n\n        /** @var string $file */\n        $file = $this->file;\n\n        return new LazyOpenStream($file, 'r+');\n    }\n\n    public function moveTo($targetPath): void\n    {\n        $this->validateActive();\n\n        if (false === $this->isStringNotEmpty($targetPath)) {\n            throw new InvalidArgumentException(\n                'Invalid path provided for move operation; must be a non-empty string'\n            );\n        }\n\n        if ($this->file) {\n            $this->moved = PHP_SAPI === 'cli'\n                ? rename($this->file, $targetPath)\n                : move_uploaded_file($this->file, $targetPath);\n        } else {\n            Utils::copyToStream(\n                $this->getStream(),\n                new LazyOpenStream($targetPath, 'w')\n            );\n\n            $this->moved = true;\n        }\n\n        if (false === $this->moved) {\n            throw new RuntimeException(\n                sprintf('Uploaded file could not be moved to %s', $targetPath)\n            );\n        }\n    }\n\n    public function getSize(): ?int\n    {\n        return $this->size;\n    }\n\n    public function getError(): int\n    {\n        return $this->error;\n    }\n\n    public function getClientFilename(): ?string\n    {\n        return $this->clientFilename;\n    }\n\n    public function getClientMediaType(): ?string\n    {\n        return $this->clientMediaType;\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Uri.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse GuzzleHttp\\Psr7\\Exception\\MalformedUriException;\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * PSR-7 URI implementation.\n *\n * @author Michael Dowling\n * @author Tobias Schultze\n * @author Matthew Weier O'Phinney\n */\nclass Uri implements UriInterface\n{\n    /**\n     * Absolute http and https URIs require a host per RFC 7230 Section 2.7\n     * but in generic URIs the host can be empty. So for http(s) URIs\n     * we apply this default host when no host is given yet to form a\n     * valid URI.\n     */\n    private const HTTP_DEFAULT_HOST = 'localhost';\n\n    private const DEFAULT_PORTS = [\n        'http'  => 80,\n        'https' => 443,\n        'ftp' => 21,\n        'gopher' => 70,\n        'nntp' => 119,\n        'news' => 119,\n        'telnet' => 23,\n        'tn3270' => 23,\n        'imap' => 143,\n        'pop' => 110,\n        'ldap' => 389,\n    ];\n\n    /**\n     * Unreserved characters for use in a regex.\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-2.3\n     */\n    private const CHAR_UNRESERVED = 'a-zA-Z0-9_\\-\\.~';\n\n    /**\n     * Sub-delims for use in a regex.\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-2.2\n     */\n    private const CHAR_SUB_DELIMS = '!\\$&\\'\\(\\)\\*\\+,;=';\n    private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26'];\n\n    /** @var string Uri scheme. */\n    private $scheme = '';\n\n    /** @var string Uri user info. */\n    private $userInfo = '';\n\n    /** @var string Uri host. */\n    private $host = '';\n\n    /** @var int|null Uri port. */\n    private $port;\n\n    /** @var string Uri path. */\n    private $path = '';\n\n    /** @var string Uri query string. */\n    private $query = '';\n\n    /** @var string Uri fragment. */\n    private $fragment = '';\n\n    /** @var string|null String representation */\n    private $composedComponents;\n\n    public function __construct(string $uri = '')\n    {\n        if ($uri !== '') {\n            $parts = self::parse($uri);\n            if ($parts === false) {\n                throw new MalformedUriException(\"Unable to parse URI: $uri\");\n            }\n            $this->applyParts($parts);\n        }\n    }\n    /**\n     * UTF-8 aware \\parse_url() replacement.\n     *\n     * The internal function produces broken output for non ASCII domain names\n     * (IDN) when used with locales other than \"C\".\n     *\n     * On the other hand, cURL understands IDN correctly only when UTF-8 locale\n     * is configured (\"C.UTF-8\", \"en_US.UTF-8\", etc.).\n     *\n     * @see https://bugs.php.net/bug.php?id=52923\n     * @see https://www.php.net/manual/en/function.parse-url.php#114817\n     * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING\n     *\n     * @return array|false\n     */\n    private static function parse(string $url)\n    {\n        // If IPv6\n        $prefix = '';\n        if (preg_match('%^(.*://\\[[0-9:a-f]+\\])(.*?)$%', $url, $matches)) {\n            /** @var array{0:string, 1:string, 2:string} $matches */\n            $prefix = $matches[1];\n            $url = $matches[2];\n        }\n\n        /** @var string */\n        $encodedUrl = preg_replace_callback(\n            '%[^:/@?&=#]+%usD',\n            static function ($matches) {\n                return urlencode($matches[0]);\n            },\n            $url\n        );\n\n        $result = parse_url($prefix . $encodedUrl);\n\n        if ($result === false) {\n            return false;\n        }\n\n        return array_map('urldecode', $result);\n    }\n\n    public function __toString(): string\n    {\n        if ($this->composedComponents === null) {\n            $this->composedComponents = self::composeComponents(\n                $this->scheme,\n                $this->getAuthority(),\n                $this->path,\n                $this->query,\n                $this->fragment\n            );\n        }\n\n        return $this->composedComponents;\n    }\n\n    /**\n     * Composes a URI reference string from its various components.\n     *\n     * Usually this method does not need to be called manually but instead is used indirectly via\n     * `Psr\\Http\\Message\\UriInterface::__toString`.\n     *\n     * PSR-7 UriInterface treats an empty component the same as a missing component as\n     * getQuery(), getFragment() etc. always return a string. This explains the slight\n     * difference to RFC 3986 Section 5.3.\n     *\n     * Another adjustment is that the authority separator is added even when the authority is missing/empty\n     * for the \"file\" scheme. This is because PHP stream functions like `file_get_contents` only work with\n     * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But\n     * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to\n     * that format).\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-5.3\n     */\n    public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment): string\n    {\n        $uri = '';\n\n        // weak type checks to also accept null until we can add scalar type hints\n        if ($scheme != '') {\n            $uri .= $scheme . ':';\n        }\n\n        if ($authority != ''|| $scheme === 'file') {\n            $uri .= '//' . $authority;\n        }\n\n        $uri .= $path;\n\n        if ($query != '') {\n            $uri .= '?' . $query;\n        }\n\n        if ($fragment != '') {\n            $uri .= '#' . $fragment;\n        }\n\n        return $uri;\n    }\n\n    /**\n     * Whether the URI has the default port of the current scheme.\n     *\n     * `Psr\\Http\\Message\\UriInterface::getPort` may return null or the standard port. This method can be used\n     * independently of the implementation.\n     */\n    public static function isDefaultPort(UriInterface $uri): bool\n    {\n        return $uri->getPort() === null\n            || (isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()]);\n    }\n\n    /**\n     * Whether the URI is absolute, i.e. it has a scheme.\n     *\n     * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true\n     * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative\n     * to another URI, the base URI. Relative references can be divided into several forms:\n     * - network-path references, e.g. '//example.com/path'\n     * - absolute-path references, e.g. '/path'\n     * - relative-path references, e.g. 'subpath'\n     *\n     * @see Uri::isNetworkPathReference\n     * @see Uri::isAbsolutePathReference\n     * @see Uri::isRelativePathReference\n     * @link https://tools.ietf.org/html/rfc3986#section-4\n     */\n    public static function isAbsolute(UriInterface $uri): bool\n    {\n        return $uri->getScheme() !== '';\n    }\n\n    /**\n     * Whether the URI is a network-path reference.\n     *\n     * A relative reference that begins with two slash characters is termed an network-path reference.\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-4.2\n     */\n    public static function isNetworkPathReference(UriInterface $uri): bool\n    {\n        return $uri->getScheme() === '' && $uri->getAuthority() !== '';\n    }\n\n    /**\n     * Whether the URI is a absolute-path reference.\n     *\n     * A relative reference that begins with a single slash character is termed an absolute-path reference.\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-4.2\n     */\n    public static function isAbsolutePathReference(UriInterface $uri): bool\n    {\n        return $uri->getScheme() === ''\n            && $uri->getAuthority() === ''\n            && isset($uri->getPath()[0])\n            && $uri->getPath()[0] === '/';\n    }\n\n    /**\n     * Whether the URI is a relative-path reference.\n     *\n     * A relative reference that does not begin with a slash character is termed a relative-path reference.\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-4.2\n     */\n    public static function isRelativePathReference(UriInterface $uri): bool\n    {\n        return $uri->getScheme() === ''\n            && $uri->getAuthority() === ''\n            && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');\n    }\n\n    /**\n     * Whether the URI is a same-document reference.\n     *\n     * A same-document reference refers to a URI that is, aside from its fragment\n     * component, identical to the base URI. When no base URI is given, only an empty\n     * URI reference (apart from its fragment) is considered a same-document reference.\n     *\n     * @param UriInterface      $uri  The URI to check\n     * @param UriInterface|null $base An optional base URI to compare against\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-4.4\n     */\n    public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool\n    {\n        if ($base !== null) {\n            $uri = UriResolver::resolve($base, $uri);\n\n            return ($uri->getScheme() === $base->getScheme())\n                && ($uri->getAuthority() === $base->getAuthority())\n                && ($uri->getPath() === $base->getPath())\n                && ($uri->getQuery() === $base->getQuery());\n        }\n\n        return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';\n    }\n\n    /**\n     * Creates a new URI with a specific query string value removed.\n     *\n     * Any existing query string values that exactly match the provided key are\n     * removed.\n     *\n     * @param UriInterface $uri URI to use as a base.\n     * @param string       $key Query string key to remove.\n     */\n    public static function withoutQueryValue(UriInterface $uri, string $key): UriInterface\n    {\n        $result = self::getFilteredQueryString($uri, [$key]);\n\n        return $uri->withQuery(implode('&', $result));\n    }\n\n    /**\n     * Creates a new URI with a specific query string value.\n     *\n     * Any existing query string values that exactly match the provided key are\n     * removed and replaced with the given key value pair.\n     *\n     * A value of null will set the query string key without a value, e.g. \"key\"\n     * instead of \"key=value\".\n     *\n     * @param UriInterface $uri   URI to use as a base.\n     * @param string       $key   Key to set.\n     * @param string|null  $value Value to set\n     */\n    public static function withQueryValue(UriInterface $uri, string $key, ?string $value): UriInterface\n    {\n        $result = self::getFilteredQueryString($uri, [$key]);\n\n        $result[] = self::generateQueryString($key, $value);\n\n        return $uri->withQuery(implode('&', $result));\n    }\n\n    /**\n     * Creates a new URI with multiple specific query string values.\n     *\n     * It has the same behavior as withQueryValue() but for an associative array of key => value.\n     *\n     * @param UriInterface               $uri           URI to use as a base.\n     * @param array<string, string|null> $keyValueArray Associative array of key and values\n     */\n    public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface\n    {\n        $result = self::getFilteredQueryString($uri, array_keys($keyValueArray));\n\n        foreach ($keyValueArray as $key => $value) {\n            $result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null);\n        }\n\n        return $uri->withQuery(implode('&', $result));\n    }\n\n    /**\n     * Creates a URI from a hash of `parse_url` components.\n     *\n     * @link http://php.net/manual/en/function.parse-url.php\n     *\n     * @throws MalformedUriException If the components do not form a valid URI.\n     */\n    public static function fromParts(array $parts): UriInterface\n    {\n        $uri = new self();\n        $uri->applyParts($parts);\n        $uri->validateState();\n\n        return $uri;\n    }\n\n    public function getScheme(): string\n    {\n        return $this->scheme;\n    }\n\n    public function getAuthority(): string\n    {\n        $authority = $this->host;\n        if ($this->userInfo !== '') {\n            $authority = $this->userInfo . '@' . $authority;\n        }\n\n        if ($this->port !== null) {\n            $authority .= ':' . $this->port;\n        }\n\n        return $authority;\n    }\n\n    public function getUserInfo(): string\n    {\n        return $this->userInfo;\n    }\n\n    public function getHost(): string\n    {\n        return $this->host;\n    }\n\n    public function getPort(): ?int\n    {\n        return $this->port;\n    }\n\n    public function getPath(): string\n    {\n        return $this->path;\n    }\n\n    public function getQuery(): string\n    {\n        return $this->query;\n    }\n\n    public function getFragment(): string\n    {\n        return $this->fragment;\n    }\n\n    public function withScheme($scheme): UriInterface\n    {\n        $scheme = $this->filterScheme($scheme);\n\n        if ($this->scheme === $scheme) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->scheme = $scheme;\n        $new->composedComponents = null;\n        $new->removeDefaultPort();\n        $new->validateState();\n\n        return $new;\n    }\n\n    public function withUserInfo($user, $password = null): UriInterface\n    {\n        $info = $this->filterUserInfoComponent($user);\n        if ($password !== null) {\n            $info .= ':' . $this->filterUserInfoComponent($password);\n        }\n\n        if ($this->userInfo === $info) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->userInfo = $info;\n        $new->composedComponents = null;\n        $new->validateState();\n\n        return $new;\n    }\n\n    public function withHost($host): UriInterface\n    {\n        $host = $this->filterHost($host);\n\n        if ($this->host === $host) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->host = $host;\n        $new->composedComponents = null;\n        $new->validateState();\n\n        return $new;\n    }\n\n    public function withPort($port): UriInterface\n    {\n        $port = $this->filterPort($port);\n\n        if ($this->port === $port) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->port = $port;\n        $new->composedComponents = null;\n        $new->removeDefaultPort();\n        $new->validateState();\n\n        return $new;\n    }\n\n    public function withPath($path): UriInterface\n    {\n        $path = $this->filterPath($path);\n\n        if ($this->path === $path) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->path = $path;\n        $new->composedComponents = null;\n        $new->validateState();\n\n        return $new;\n    }\n\n    public function withQuery($query): UriInterface\n    {\n        $query = $this->filterQueryAndFragment($query);\n\n        if ($this->query === $query) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->query = $query;\n        $new->composedComponents = null;\n\n        return $new;\n    }\n\n    public function withFragment($fragment): UriInterface\n    {\n        $fragment = $this->filterQueryAndFragment($fragment);\n\n        if ($this->fragment === $fragment) {\n            return $this;\n        }\n\n        $new = clone $this;\n        $new->fragment = $fragment;\n        $new->composedComponents = null;\n\n        return $new;\n    }\n\n    /**\n     * Apply parse_url parts to a URI.\n     *\n     * @param array $parts Array of parse_url parts to apply.\n     */\n    private function applyParts(array $parts): void\n    {\n        $this->scheme = isset($parts['scheme'])\n            ? $this->filterScheme($parts['scheme'])\n            : '';\n        $this->userInfo = isset($parts['user'])\n            ? $this->filterUserInfoComponent($parts['user'])\n            : '';\n        $this->host = isset($parts['host'])\n            ? $this->filterHost($parts['host'])\n            : '';\n        $this->port = isset($parts['port'])\n            ? $this->filterPort($parts['port'])\n            : null;\n        $this->path = isset($parts['path'])\n            ? $this->filterPath($parts['path'])\n            : '';\n        $this->query = isset($parts['query'])\n            ? $this->filterQueryAndFragment($parts['query'])\n            : '';\n        $this->fragment = isset($parts['fragment'])\n            ? $this->filterQueryAndFragment($parts['fragment'])\n            : '';\n        if (isset($parts['pass'])) {\n            $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']);\n        }\n\n        $this->removeDefaultPort();\n    }\n\n    /**\n     * @param mixed $scheme\n     *\n     * @throws \\InvalidArgumentException If the scheme is invalid.\n     */\n    private function filterScheme($scheme): string\n    {\n        if (!is_string($scheme)) {\n            throw new \\InvalidArgumentException('Scheme must be a string');\n        }\n\n        return \\strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');\n    }\n\n    /**\n     * @param mixed $component\n     *\n     * @throws \\InvalidArgumentException If the user info is invalid.\n     */\n    private function filterUserInfoComponent($component): string\n    {\n        if (!is_string($component)) {\n            throw new \\InvalidArgumentException('User info must be a string');\n        }\n\n        return preg_replace_callback(\n            '/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/',\n            [$this, 'rawurlencodeMatchZero'],\n            $component\n        );\n    }\n\n    /**\n     * @param mixed $host\n     *\n     * @throws \\InvalidArgumentException If the host is invalid.\n     */\n    private function filterHost($host): string\n    {\n        if (!is_string($host)) {\n            throw new \\InvalidArgumentException('Host must be a string');\n        }\n\n        return \\strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');\n    }\n\n    /**\n     * @param mixed $port\n     *\n     * @throws \\InvalidArgumentException If the port is invalid.\n     */\n    private function filterPort($port): ?int\n    {\n        if ($port === null) {\n            return null;\n        }\n\n        $port = (int) $port;\n        if (0 > $port || 0xffff < $port) {\n            throw new \\InvalidArgumentException(\n                sprintf('Invalid port: %d. Must be between 0 and 65535', $port)\n            );\n        }\n\n        return $port;\n    }\n\n    /**\n     * @param string[] $keys\n     *\n     * @return string[]\n     */\n    private static function getFilteredQueryString(UriInterface $uri, array $keys): array\n    {\n        $current = $uri->getQuery();\n\n        if ($current === '') {\n            return [];\n        }\n\n        $decodedKeys = array_map('rawurldecode', $keys);\n\n        return array_filter(explode('&', $current), function ($part) use ($decodedKeys) {\n            return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true);\n        });\n    }\n\n    private static function generateQueryString(string $key, ?string $value): string\n    {\n        // Query string separators (\"=\", \"&\") within the key or value need to be encoded\n        // (while preventing double-encoding) before setting the query string. All other\n        // chars that need percent-encoding will be encoded by withQuery().\n        $queryString = strtr($key, self::QUERY_SEPARATORS_REPLACEMENT);\n\n        if ($value !== null) {\n            $queryString .= '=' . strtr($value, self::QUERY_SEPARATORS_REPLACEMENT);\n        }\n\n        return $queryString;\n    }\n\n    private function removeDefaultPort(): void\n    {\n        if ($this->port !== null && self::isDefaultPort($this)) {\n            $this->port = null;\n        }\n    }\n\n    /**\n     * Filters the path of a URI\n     *\n     * @param mixed $path\n     *\n     * @throws \\InvalidArgumentException If the path is invalid.\n     */\n    private function filterPath($path): string\n    {\n        if (!is_string($path)) {\n            throw new \\InvalidArgumentException('Path must be a string');\n        }\n\n        return preg_replace_callback(\n            '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/]++|%(?![A-Fa-f0-9]{2}))/',\n            [$this, 'rawurlencodeMatchZero'],\n            $path\n        );\n    }\n\n    /**\n     * Filters the query string or fragment of a URI.\n     *\n     * @param mixed $str\n     *\n     * @throws \\InvalidArgumentException If the query or fragment is invalid.\n     */\n    private function filterQueryAndFragment($str): string\n    {\n        if (!is_string($str)) {\n            throw new \\InvalidArgumentException('Query and fragment must be a string');\n        }\n\n        return preg_replace_callback(\n            '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/',\n            [$this, 'rawurlencodeMatchZero'],\n            $str\n        );\n    }\n\n    private function rawurlencodeMatchZero(array $match): string\n    {\n        return rawurlencode($match[0]);\n    }\n\n    private function validateState(): void\n    {\n        if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {\n            $this->host = self::HTTP_DEFAULT_HOST;\n        }\n\n        if ($this->getAuthority() === '') {\n            if (0 === strpos($this->path, '//')) {\n                throw new MalformedUriException('The path of a URI without an authority must not start with two slashes \"//\"');\n            }\n            if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) {\n                throw new MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon');\n            }\n        } elseif (isset($this->path[0]) && $this->path[0] !== '/') {\n            throw new MalformedUriException('The path of a URI with an authority must start with a slash \"/\" or be empty');\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/UriNormalizer.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Provides methods to normalize and compare URIs.\n *\n * @author Tobias Schultze\n *\n * @link https://tools.ietf.org/html/rfc3986#section-6\n */\nfinal class UriNormalizer\n{\n    /**\n     * Default normalizations which only include the ones that preserve semantics.\n     */\n    public const PRESERVING_NORMALIZATIONS =\n        self::CAPITALIZE_PERCENT_ENCODING |\n        self::DECODE_UNRESERVED_CHARACTERS |\n        self::CONVERT_EMPTY_PATH |\n        self::REMOVE_DEFAULT_HOST |\n        self::REMOVE_DEFAULT_PORT |\n        self::REMOVE_DOT_SEGMENTS;\n\n    /**\n     * All letters within a percent-encoding triplet (e.g., \"%3A\") are case-insensitive, and should be capitalized.\n     *\n     * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b\n     */\n    public const CAPITALIZE_PERCENT_ENCODING = 1;\n\n    /**\n     * Decodes percent-encoded octets of unreserved characters.\n     *\n     * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39),\n     * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and,\n     * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.\n     *\n     * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/\n     */\n    public const DECODE_UNRESERVED_CHARACTERS = 2;\n\n    /**\n     * Converts the empty path to \"/\" for http and https URIs.\n     *\n     * Example: http://example.org → http://example.org/\n     */\n    public const CONVERT_EMPTY_PATH = 4;\n\n    /**\n     * Removes the default host of the given URI scheme from the URI.\n     *\n     * Only the \"file\" scheme defines the default host \"localhost\".\n     * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile`\n     * are equivalent according to RFC 3986. The first format is not accepted\n     * by PHPs stream functions and thus already normalized implicitly to the\n     * second format in the Uri class. See `GuzzleHttp\\Psr7\\Uri::composeComponents`.\n     *\n     * Example: file://localhost/myfile → file:///myfile\n     */\n    public const REMOVE_DEFAULT_HOST = 8;\n\n    /**\n     * Removes the default port of the given URI scheme from the URI.\n     *\n     * Example: http://example.org:80/ → http://example.org/\n     */\n    public const REMOVE_DEFAULT_PORT = 16;\n\n    /**\n     * Removes unnecessary dot-segments.\n     *\n     * Dot-segments in relative-path references are not removed as it would\n     * change the semantics of the URI reference.\n     *\n     * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html\n     */\n    public const REMOVE_DOT_SEGMENTS = 32;\n\n    /**\n     * Paths which include two or more adjacent slashes are converted to one.\n     *\n     * Webservers usually ignore duplicate slashes and treat those URIs equivalent.\n     * But in theory those URIs do not need to be equivalent. So this normalization\n     * may change the semantics. Encoded slashes (%2F) are not removed.\n     *\n     * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html\n     */\n    public const REMOVE_DUPLICATE_SLASHES = 64;\n\n    /**\n     * Sort query parameters with their values in alphabetical order.\n     *\n     * However, the order of parameters in a URI may be significant (this is not defined by the standard).\n     * So this normalization is not safe and may change the semantics of the URI.\n     *\n     * Example: ?lang=en&article=fred → ?article=fred&lang=en\n     *\n     * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the\n     * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.\n     */\n    public const SORT_QUERY_PARAMETERS = 128;\n\n    /**\n     * Returns a normalized URI.\n     *\n     * The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.\n     * This methods adds additional normalizations that can be configured with the $flags parameter.\n     *\n     * PSR-7 UriInterface cannot distinguish between an empty component and a missing component as\n     * getQuery(), getFragment() etc. always return a string. This means the URIs \"/?#\" and \"/\" are\n     * treated equivalent which is not necessarily true according to RFC 3986. But that difference\n     * is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well.\n     *\n     * @param UriInterface $uri   The URI to normalize\n     * @param int          $flags A bitmask of normalizations to apply, see constants\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-6.2\n     */\n    public static function normalize(UriInterface $uri, int $flags = self::PRESERVING_NORMALIZATIONS): UriInterface\n    {\n        if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {\n            $uri = self::capitalizePercentEncoding($uri);\n        }\n\n        if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {\n            $uri = self::decodeUnreservedCharacters($uri);\n        }\n\n        if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' &&\n            ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')\n        ) {\n            $uri = $uri->withPath('/');\n        }\n\n        if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {\n            $uri = $uri->withHost('');\n        }\n\n        if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) {\n            $uri = $uri->withPort(null);\n        }\n\n        if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) {\n            $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath()));\n        }\n\n        if ($flags & self::REMOVE_DUPLICATE_SLASHES) {\n            $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath()));\n        }\n\n        if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {\n            $queryKeyValues = explode('&', $uri->getQuery());\n            sort($queryKeyValues);\n            $uri = $uri->withQuery(implode('&', $queryKeyValues));\n        }\n\n        return $uri;\n    }\n\n    /**\n     * Whether two URIs can be considered equivalent.\n     *\n     * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also\n     * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be\n     * resolved against the same base URI. If this is not the case, determination of equivalence or difference of\n     * relative references does not mean anything.\n     *\n     * @param UriInterface $uri1           An URI to compare\n     * @param UriInterface $uri2           An URI to compare\n     * @param int          $normalizations A bitmask of normalizations to apply, see constants\n     *\n     * @link https://tools.ietf.org/html/rfc3986#section-6.1\n     */\n    public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS): bool\n    {\n        return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);\n    }\n\n    private static function capitalizePercentEncoding(UriInterface $uri): UriInterface\n    {\n        $regex = '/(?:%[A-Fa-f0-9]{2})++/';\n\n        $callback = function (array $match) {\n            return strtoupper($match[0]);\n        };\n\n        return\n            $uri->withPath(\n                preg_replace_callback($regex, $callback, $uri->getPath())\n            )->withQuery(\n                preg_replace_callback($regex, $callback, $uri->getQuery())\n            );\n    }\n\n    private static function decodeUnreservedCharacters(UriInterface $uri): UriInterface\n    {\n        $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';\n\n        $callback = function (array $match) {\n            return rawurldecode($match[0]);\n        };\n\n        return\n            $uri->withPath(\n                preg_replace_callback($regex, $callback, $uri->getPath())\n            )->withQuery(\n                preg_replace_callback($regex, $callback, $uri->getQuery())\n            );\n    }\n\n    private function __construct()\n    {\n        // cannot be instantiated\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/UriResolver.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\UriInterface;\n\n/**\n * Resolves a URI reference in the context of a base URI and the opposite way.\n *\n * @author Tobias Schultze\n *\n * @link https://tools.ietf.org/html/rfc3986#section-5\n */\nfinal class UriResolver\n{\n    /**\n     * Removes dot segments from a path and returns the new path.\n     *\n     * @link http://tools.ietf.org/html/rfc3986#section-5.2.4\n     */\n    public static function removeDotSegments(string $path): string\n    {\n        if ($path === '' || $path === '/') {\n            return $path;\n        }\n\n        $results = [];\n        $segments = explode('/', $path);\n        foreach ($segments as $segment) {\n            if ($segment === '..') {\n                array_pop($results);\n            } elseif ($segment !== '.') {\n                $results[] = $segment;\n            }\n        }\n\n        $newPath = implode('/', $results);\n\n        if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {\n            // Re-add the leading slash if necessary for cases like \"/..\"\n            $newPath = '/' . $newPath;\n        } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) {\n            // Add the trailing slash if necessary\n            // If newPath is not empty, then $segment must be set and is the last segment from the foreach\n            $newPath .= '/';\n        }\n\n        return $newPath;\n    }\n\n    /**\n     * Converts the relative URI into a new URI that is resolved against the base URI.\n     *\n     * @link http://tools.ietf.org/html/rfc3986#section-5.2\n     */\n    public static function resolve(UriInterface $base, UriInterface $rel): UriInterface\n    {\n        if ((string) $rel === '') {\n            // we can simply return the same base URI instance for this same-document reference\n            return $base;\n        }\n\n        if ($rel->getScheme() != '') {\n            return $rel->withPath(self::removeDotSegments($rel->getPath()));\n        }\n\n        if ($rel->getAuthority() != '') {\n            $targetAuthority = $rel->getAuthority();\n            $targetPath = self::removeDotSegments($rel->getPath());\n            $targetQuery = $rel->getQuery();\n        } else {\n            $targetAuthority = $base->getAuthority();\n            if ($rel->getPath() === '') {\n                $targetPath = $base->getPath();\n                $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();\n            } else {\n                if ($rel->getPath()[0] === '/') {\n                    $targetPath = $rel->getPath();\n                } else {\n                    if ($targetAuthority != '' && $base->getPath() === '') {\n                        $targetPath = '/' . $rel->getPath();\n                    } else {\n                        $lastSlashPos = strrpos($base->getPath(), '/');\n                        if ($lastSlashPos === false) {\n                            $targetPath = $rel->getPath();\n                        } else {\n                            $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();\n                        }\n                    }\n                }\n                $targetPath = self::removeDotSegments($targetPath);\n                $targetQuery = $rel->getQuery();\n            }\n        }\n\n        return new Uri(Uri::composeComponents(\n            $base->getScheme(),\n            $targetAuthority,\n            $targetPath,\n            $targetQuery,\n            $rel->getFragment()\n        ));\n    }\n\n    /**\n     * Returns the target URI as a relative reference from the base URI.\n     *\n     * This method is the counterpart to resolve():\n     *\n     *    (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))\n     *\n     * One use-case is to use the current request URI as base URI and then generate relative links in your documents\n     * to reduce the document size or offer self-contained downloadable document archives.\n     *\n     *    $base = new Uri('http://example.com/a/b/');\n     *    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c'));  // prints 'c'.\n     *    echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y'));  // prints '../x/y'.\n     *    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.\n     *    echo UriResolver::relativize($base, new Uri('http://example.org/a/b/'));   // prints '//example.org/a/b/'.\n     *\n     * This method also accepts a target that is already relative and will try to relativize it further. Only a\n     * relative-path reference will be returned as-is.\n     *\n     *    echo UriResolver::relativize($base, new Uri('/a/b/c'));  // prints 'c' as well\n     */\n    public static function relativize(UriInterface $base, UriInterface $target): UriInterface\n    {\n        if ($target->getScheme() !== '' &&\n            ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')\n        ) {\n            return $target;\n        }\n\n        if (Uri::isRelativePathReference($target)) {\n            // As the target is already highly relative we return it as-is. It would be possible to resolve\n            // the target with `$target = self::resolve($base, $target);` and then try make it more relative\n            // by removing a duplicate query. But let's not do that automatically.\n            return $target;\n        }\n\n        if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {\n            return $target->withScheme('');\n        }\n\n        // We must remove the path before removing the authority because if the path starts with two slashes, the URI\n        // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also\n        // invalid.\n        $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');\n\n        if ($base->getPath() !== $target->getPath()) {\n            return $emptyPathUri->withPath(self::getRelativePath($base, $target));\n        }\n\n        if ($base->getQuery() === $target->getQuery()) {\n            // Only the target fragment is left. And it must be returned even if base and target fragment are the same.\n            return $emptyPathUri->withQuery('');\n        }\n\n        // If the base URI has a query but the target has none, we cannot return an empty path reference as it would\n        // inherit the base query component when resolving.\n        if ($target->getQuery() === '') {\n            $segments = explode('/', $target->getPath());\n            /** @var string $lastSegment */\n            $lastSegment = end($segments);\n\n            return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);\n        }\n\n        return $emptyPathUri;\n    }\n\n    private static function getRelativePath(UriInterface $base, UriInterface $target): string\n    {\n        $sourceSegments = explode('/', $base->getPath());\n        $targetSegments = explode('/', $target->getPath());\n        array_pop($sourceSegments);\n        $targetLastSegment = array_pop($targetSegments);\n        foreach ($sourceSegments as $i => $segment) {\n            if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {\n                unset($sourceSegments[$i], $targetSegments[$i]);\n            } else {\n                break;\n            }\n        }\n        $targetSegments[] = $targetLastSegment;\n        $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments);\n\n        // A reference to am empty last segment or an empty first sub-segment must be prefixed with \"./\".\n        // This also applies to a segment with a colon character (e.g., \"file:colon\") that cannot be used\n        // as the first segment of a relative-path reference, as it would be mistaken for a scheme name.\n        if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) {\n            $relativePath = \"./$relativePath\";\n        } elseif ('/' === $relativePath[0]) {\n            if ($base->getAuthority() != '' && $base->getPath() === '') {\n                // In this case an extra slash is added by resolve() automatically. So we must not add one here.\n                $relativePath = \".$relativePath\";\n            } else {\n                $relativePath = \"./$relativePath\";\n            }\n        }\n\n        return $relativePath;\n    }\n\n    private function __construct()\n    {\n        // cannot be instantiated\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/src/Utils.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace GuzzleHttp\\Psr7;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Message\\StreamInterface;\nuse Psr\\Http\\Message\\UriInterface;\n\nfinal class Utils\n{\n    /**\n     * Remove the items given by the keys, case insensitively from the data.\n     *\n     * @param string[] $keys\n     */\n    public static function caselessRemove(array $keys, array $data): array\n    {\n        $result = [];\n\n        foreach ($keys as &$key) {\n            $key = strtolower($key);\n        }\n\n        foreach ($data as $k => $v) {\n            if (!is_string($k) || !in_array(strtolower($k), $keys)) {\n                $result[$k] = $v;\n            }\n        }\n\n        return $result;\n    }\n\n    /**\n     * Copy the contents of a stream into another stream until the given number\n     * of bytes have been read.\n     *\n     * @param StreamInterface $source Stream to read from\n     * @param StreamInterface $dest   Stream to write to\n     * @param int             $maxLen Maximum number of bytes to read. Pass -1\n     *                                to read the entire stream.\n     *\n     * @throws \\RuntimeException on error.\n     */\n    public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void\n    {\n        $bufferSize = 8192;\n\n        if ($maxLen === -1) {\n            while (!$source->eof()) {\n                if (!$dest->write($source->read($bufferSize))) {\n                    break;\n                }\n            }\n        } else {\n            $remaining = $maxLen;\n            while ($remaining > 0 && !$source->eof()) {\n                $buf = $source->read(min($bufferSize, $remaining));\n                $len = strlen($buf);\n                if (!$len) {\n                    break;\n                }\n                $remaining -= $len;\n                $dest->write($buf);\n            }\n        }\n    }\n\n    /**\n     * Copy the contents of a stream into a string until the given number of\n     * bytes have been read.\n     *\n     * @param StreamInterface $stream Stream to read\n     * @param int             $maxLen Maximum number of bytes to read. Pass -1\n     *                                to read the entire stream.\n     *\n     * @throws \\RuntimeException on error.\n     */\n    public static function copyToString(StreamInterface $stream, int $maxLen = -1): string\n    {\n        $buffer = '';\n\n        if ($maxLen === -1) {\n            while (!$stream->eof()) {\n                $buf = $stream->read(1048576);\n                if ($buf === '') {\n                    break;\n                }\n                $buffer .= $buf;\n            }\n            return $buffer;\n        }\n\n        $len = 0;\n        while (!$stream->eof() && $len < $maxLen) {\n            $buf = $stream->read($maxLen - $len);\n            if ($buf === '') {\n                break;\n            }\n            $buffer .= $buf;\n            $len = strlen($buffer);\n        }\n\n        return $buffer;\n    }\n\n    /**\n     * Calculate a hash of a stream.\n     *\n     * This method reads the entire stream to calculate a rolling hash, based\n     * on PHP's `hash_init` functions.\n     *\n     * @param StreamInterface $stream    Stream to calculate the hash for\n     * @param string          $algo      Hash algorithm (e.g. md5, crc32, etc)\n     * @param bool            $rawOutput Whether or not to use raw output\n     *\n     * @throws \\RuntimeException on error.\n     */\n    public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string\n    {\n        $pos = $stream->tell();\n\n        if ($pos > 0) {\n            $stream->rewind();\n        }\n\n        $ctx = hash_init($algo);\n        while (!$stream->eof()) {\n            hash_update($ctx, $stream->read(1048576));\n        }\n\n        $out = hash_final($ctx, (bool) $rawOutput);\n        $stream->seek($pos);\n\n        return $out;\n    }\n\n    /**\n     * Clone and modify a request with the given changes.\n     *\n     * This method is useful for reducing the number of clones needed to mutate\n     * a message.\n     *\n     * The changes can be one of:\n     * - method: (string) Changes the HTTP method.\n     * - set_headers: (array) Sets the given headers.\n     * - remove_headers: (array) Remove the given headers.\n     * - body: (mixed) Sets the given body.\n     * - uri: (UriInterface) Set the URI.\n     * - query: (string) Set the query string value of the URI.\n     * - version: (string) Set the protocol version.\n     *\n     * @param RequestInterface $request Request to clone and modify.\n     * @param array            $changes Changes to apply.\n     */\n    public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface\n    {\n        if (!$changes) {\n            return $request;\n        }\n\n        $headers = $request->getHeaders();\n\n        if (!isset($changes['uri'])) {\n            $uri = $request->getUri();\n        } else {\n            // Remove the host header if one is on the URI\n            if ($host = $changes['uri']->getHost()) {\n                $changes['set_headers']['Host'] = $host;\n\n                if ($port = $changes['uri']->getPort()) {\n                    $standardPorts = ['http' => 80, 'https' => 443];\n                    $scheme = $changes['uri']->getScheme();\n                    if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {\n                        $changes['set_headers']['Host'] .= ':' . $port;\n                    }\n                }\n            }\n            $uri = $changes['uri'];\n        }\n\n        if (!empty($changes['remove_headers'])) {\n            $headers = self::caselessRemove($changes['remove_headers'], $headers);\n        }\n\n        if (!empty($changes['set_headers'])) {\n            $headers = self::caselessRemove(array_keys($changes['set_headers']), $headers);\n            $headers = $changes['set_headers'] + $headers;\n        }\n\n        if (isset($changes['query'])) {\n            $uri = $uri->withQuery($changes['query']);\n        }\n\n        if ($request instanceof ServerRequestInterface) {\n            $new = (new ServerRequest(\n                $changes['method'] ?? $request->getMethod(),\n                $uri,\n                $headers,\n                $changes['body'] ?? $request->getBody(),\n                $changes['version'] ?? $request->getProtocolVersion(),\n                $request->getServerParams()\n            ))\n            ->withParsedBody($request->getParsedBody())\n            ->withQueryParams($request->getQueryParams())\n            ->withCookieParams($request->getCookieParams())\n            ->withUploadedFiles($request->getUploadedFiles());\n\n            foreach ($request->getAttributes() as $key => $value) {\n                $new = $new->withAttribute($key, $value);\n            }\n\n            return $new;\n        }\n\n        return new Request(\n            $changes['method'] ?? $request->getMethod(),\n            $uri,\n            $headers,\n            $changes['body'] ?? $request->getBody(),\n            $changes['version'] ?? $request->getProtocolVersion()\n        );\n    }\n\n    /**\n     * Read a line from the stream up to the maximum allowed buffer length.\n     *\n     * @param StreamInterface $stream    Stream to read from\n     * @param int|null        $maxLength Maximum buffer length\n     */\n    public static function readLine(StreamInterface $stream, ?int $maxLength = null): string\n    {\n        $buffer = '';\n        $size = 0;\n\n        while (!$stream->eof()) {\n            if ('' === ($byte = $stream->read(1))) {\n                return $buffer;\n            }\n            $buffer .= $byte;\n            // Break when a new line is found or the max length - 1 is reached\n            if ($byte === \"\\n\" || ++$size === $maxLength - 1) {\n                break;\n            }\n        }\n\n        return $buffer;\n    }\n\n    /**\n     * Create a new stream based on the input type.\n     *\n     * Options is an associative array that can contain the following keys:\n     * - metadata: Array of custom metadata.\n     * - size: Size of the stream.\n     *\n     * This method accepts the following `$resource` types:\n     * - `Psr\\Http\\Message\\StreamInterface`: Returns the value as-is.\n     * - `string`: Creates a stream object that uses the given string as the contents.\n     * - `resource`: Creates a stream object that wraps the given PHP stream resource.\n     * - `Iterator`: If the provided value implements `Iterator`, then a read-only\n     *   stream object will be created that wraps the given iterable. Each time the\n     *   stream is read from, data from the iterator will fill a buffer and will be\n     *   continuously called until the buffer is equal to the requested read size.\n     *   Subsequent read calls will first read from the buffer and then call `next`\n     *   on the underlying iterator until it is exhausted.\n     * - `object` with `__toString()`: If the object has the `__toString()` method,\n     *   the object will be cast to a string and then a stream will be returned that\n     *   uses the string value.\n     * - `NULL`: When `null` is passed, an empty stream object is returned.\n     * - `callable` When a callable is passed, a read-only stream object will be\n     *   created that invokes the given callable. The callable is invoked with the\n     *   number of suggested bytes to read. The callable can return any number of\n     *   bytes, but MUST return `false` when there is no more data to return. The\n     *   stream object that wraps the callable will invoke the callable until the\n     *   number of requested bytes are available. Any additional bytes will be\n     *   buffered and used in subsequent reads.\n     *\n     * @param resource|string|int|float|bool|StreamInterface|callable|\\Iterator|null $resource Entity body data\n     * @param array{size?: int, metadata?: array}                                    $options  Additional options\n     *\n     * @throws \\InvalidArgumentException if the $resource arg is not valid.\n     */\n    public static function streamFor($resource = '', array $options = []): StreamInterface\n    {\n        if (is_scalar($resource)) {\n            $stream = self::tryFopen('php://temp', 'r+');\n            if ($resource !== '') {\n                fwrite($stream, (string) $resource);\n                fseek($stream, 0);\n            }\n            return new Stream($stream, $options);\n        }\n\n        switch (gettype($resource)) {\n            case 'resource':\n                /*\n                 * The 'php://input' is a special stream with quirks and inconsistencies.\n                 * We avoid using that stream by reading it into php://temp\n                 */\n\n                /** @var resource $resource */\n                if ((\\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') {\n                    $stream = self::tryFopen('php://temp', 'w+');\n                    fwrite($stream, stream_get_contents($resource));\n                    fseek($stream, 0);\n                    $resource = $stream;\n                }\n                return new Stream($resource, $options);\n            case 'object':\n                /** @var object $resource */\n                if ($resource instanceof StreamInterface) {\n                    return $resource;\n                } elseif ($resource instanceof \\Iterator) {\n                    return new PumpStream(function () use ($resource) {\n                        if (!$resource->valid()) {\n                            return false;\n                        }\n                        $result = $resource->current();\n                        $resource->next();\n                        return $result;\n                    }, $options);\n                } elseif (method_exists($resource, '__toString')) {\n                    return self::streamFor((string) $resource, $options);\n                }\n                break;\n            case 'NULL':\n                return new Stream(self::tryFopen('php://temp', 'r+'), $options);\n        }\n\n        if (is_callable($resource)) {\n            return new PumpStream($resource, $options);\n        }\n\n        throw new \\InvalidArgumentException('Invalid resource type: ' . gettype($resource));\n    }\n\n    /**\n     * Safely opens a PHP stream resource using a filename.\n     *\n     * When fopen fails, PHP normally raises a warning. This function adds an\n     * error handler that checks for errors and throws an exception instead.\n     *\n     * @param string $filename File to open\n     * @param string $mode     Mode used to open the file\n     *\n     * @return resource\n     *\n     * @throws \\RuntimeException if the file cannot be opened\n     */\n    public static function tryFopen(string $filename, string $mode)\n    {\n        $ex = null;\n        set_error_handler(static function (int $errno, string $errstr) use ($filename, $mode, &$ex): bool {\n            $ex = new \\RuntimeException(sprintf(\n                'Unable to open \"%s\" using mode \"%s\": %s',\n                $filename,\n                $mode,\n                $errstr\n            ));\n\n            return true;\n        });\n\n        try {\n            /** @var resource $handle */\n            $handle = fopen($filename, $mode);\n        } catch (\\Throwable $e) {\n            $ex = new \\RuntimeException(sprintf(\n                'Unable to open \"%s\" using mode \"%s\": %s',\n                $filename,\n                $mode,\n                $e->getMessage()\n            ), 0, $e);\n        }\n\n        restore_error_handler();\n\n        if ($ex) {\n            /** @var $ex \\RuntimeException */\n            throw $ex;\n        }\n\n        return $handle;\n    }\n\n    /**\n     * Returns a UriInterface for the given value.\n     *\n     * This function accepts a string or UriInterface and returns a\n     * UriInterface for the given value. If the value is already a\n     * UriInterface, it is returned as-is.\n     *\n     * @param string|UriInterface $uri\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public static function uriFor($uri): UriInterface\n    {\n        if ($uri instanceof UriInterface) {\n            return $uri;\n        }\n\n        if (is_string($uri)) {\n            return new Uri($uri);\n        }\n\n        throw new \\InvalidArgumentException('URI must be a string or UriInterface');\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/vendor-bin/php-cs-fixer/composer.json",
    "content": "{\n    \"require\": {\n        \"php\": \"^7.2.5 || ^8.0\",\n        \"friendsofphp/php-cs-fixer\": \"3.2.1\"\n    },\n    \"config\": {\n        \"preferred-install\": \"dist\"\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/vendor-bin/phpstan/composer.json",
    "content": "{\n    \"require\": {\n        \"php\": \"^7.2.5 || ^8.0\",\n        \"phpstan/phpstan\": \"0.12.81\",\n        \"phpstan/phpstan-deprecation-rules\": \"0.12.6\"\n    },\n    \"config\": {\n        \"preferred-install\": \"dist\"\n    }\n}\n"
  },
  {
    "path": "vendor/guzzlehttp/psr7/vendor-bin/psalm/composer.json",
    "content": "{\n    \"require\": {\n        \"php\": \"^7.2.5 || ^8.0\",\n        \"psalm/phar\": \"4.6.2\"\n    },\n    \"config\": {\n        \"preferred-install\": \"dist\"\n    }\n}\n"
  },
  {
    "path": "vendor/jaeger/phpquery-single/README.md",
    "content": "# phpQuery-single\nphpQuery onefile composer.Continuous maintenance,Welcome PR.\n\n`QueryList` base on phpQuery: https://github.com/jae-jae/QueryList\n\nphpQuery单文件版本,持续维护，欢迎PR.\n> phpQuery项目主页:http://code.google.com/p/phpquery/\n\n`QueryList`是基于phpQuery的采集工具: https://github.com/jae-jae/QueryList\n\n## Composer Installation\nPackagist: https://packagist.org/packages/jaeger/phpquery-single\n```\ncomposer require jaeger/phpquery-single\n```\n\n## Usage\n```php\n$html = <<<STR\n<div id=\"one\">\n    <div class=\"two\">\n        <a href=\"http://querylist.cc\">QueryList官网</a>\n        <img src=\"http://querylist.cc/1.jpg\" alt=\"这是图片\">\n        <img src=\"http://querylist.cc/2.jpg\" alt=\"这是图片2\">\n    </div>\n    <span>其它的<b>一些</b>文本</span>\n</div>        \nSTR;\n\n$doc = phpQuery::newDocumentHTML($html);\n\n$src = $doc->find('.two img:eq(0)')->attr('src');\n\necho $src;\n// http://querylist.cc/1.jpg\n```"
  },
  {
    "path": "vendor/jaeger/phpquery-single/composer.json",
    "content": "{\n    \"name\": \"jaeger/phpquery-single\",\n    \"description\": \"phpQuery单文件版本，是Querylist的依赖(http://querylist.cc/)，phpQuery项目主页:http://code.google.com/p/phpquery/\",\n    \"homepage\": \"http://code.google.com/p/phpquery/\",\n    \"license\": \"MIT\",\n    \"require\": {\n    \t\"PHP\":\">=5.3.0\"\n    },\n    \"authors\": [\n        {\n            \"name\": \"Tobiasz Cudnik\"\n            ,\"email\": \"tobiasz.cudnik@gmail.com\"\n            ,\"homepage\": \"https://github.com/TobiaszCudnik\"\n            ,\"role\": \"Developer\"\n        } \n        ,{\n            \"name\": \"Jaeger\",\n            \"role\": \"Packager\"\n        }\n    ],\n    \"autoload\":{\n        \"classmap\":[\"phpQuery.php\"]\n    }\n}\n"
  },
  {
    "path": "vendor/jaeger/phpquery-single/phpQuery.php",
    "content": "<?php\n/**\n * phpQuery is a server-side, chainable, CSS3 selector driven\n * Document Object Model (DOM) API based on jQuery JavaScript Library.\n *\n * @version 1.0.0\n * @link http://code.google.com/p/phpquery/\n * @link http://phpquery-library.blogspot.com/\n * @link http://jquery.com/\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @license http://www.opensource.org/licenses/mit-license.php MIT License\n * @package phpQuery\n */\n\n// class names for instanceof\n// TODO move them as class constants into phpQuery\ndefine('DOMDOCUMENT', 'DOMDocument');\ndefine('DOMELEMENT', 'DOMElement');\ndefine('DOMNODELIST', 'DOMNodeList');\ndefine('DOMNODE', 'DOMNode');\n\n/**\n * DOMEvent class.\n *\n * Based on\n * @link http://developer.mozilla.org/En/DOM:event\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @package phpQuery\n * @todo implement ArrayAccess ?\n */\nclass DOMEvent {\n\t/**\n\t * Returns a boolean indicating whether the event bubbles up through the DOM or not.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $bubbles = true;\n\t/**\n\t * Returns a boolean indicating whether the event is cancelable.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $cancelable = true;\n\t/**\n\t * Returns a reference to the currently registered target for the event.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $currentTarget;\n\t/**\n\t * Returns detail about the event, depending on the type of event.\n\t *\n\t * @var unknown_type\n\t * @link http://developer.mozilla.org/en/DOM/event.detail\n\t */\n\tpublic $detail;\t// ???\n\t/**\n\t * Used to indicate which phase of the event flow is currently being evaluated.\n\t *\n\t * NOT IMPLEMENTED\n\t *\n\t * @var unknown_type\n\t * @link http://developer.mozilla.org/en/DOM/event.eventPhase\n\t */\n\tpublic $eventPhase;\t// ???\n\t/**\n\t * The explicit original target of the event (Mozilla-specific).\n\t *\n\t * NOT IMPLEMENTED\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $explicitOriginalTarget; // moz only\n\t/**\n\t * The original target of the event, before any retargetings (Mozilla-specific).\n\t *\n\t * NOT IMPLEMENTED\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $originalTarget;\t// moz only\n\t/**\n\t * Identifies a secondary target for the event.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $relatedTarget;\n\t/**\n\t * Returns a reference to the target to which the event was originally dispatched.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $target;\n\t/**\n\t * Returns the time that the event was created.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic $timeStamp;\n\t/**\n\t * Returns the name of the event (case-insensitive).\n\t */\n\tpublic $type;\n\tpublic $runDefault = true;\n\tpublic $data = null;\n\tpublic function __construct($data) {\n\t\tforeach($data as $k => $v) {\n\t\t\t$this->$k = $v;\n\t\t}\n\t\tif (! $this->timeStamp)\n\t\t\t$this->timeStamp = time();\n\t}\n\t/**\n\t * Cancels the event (if it is cancelable).\n\t *\n\t */\n\tpublic function preventDefault() {\n\t\t$this->runDefault = false;\n\t}\n\t/**\n\t * Stops the propagation of events further along in the DOM.\n\t *\n\t */\n\tpublic function stopPropagation() {\n\t\t$this->bubbles = false;\n\t}\n}\n\n\n/**\n * DOMDocumentWrapper class simplifies work with DOMDocument.\n *\n * Know bug:\n * - in XHTML fragments, <br /> changes to <br clear=\"none\" />\n *\n * @todo check XML catalogs compatibility\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @package phpQuery\n */\nclass DOMDocumentWrapper {\n\t/**\n\t * @var DOMDocument\n\t */\n\tpublic $document;\n\tpublic $id;\n\t/**\n\t * @todo Rewrite as method and quess if null.\n\t * @var unknown_type\n\t */\n\tpublic $contentType = '';\n\tpublic $xpath;\n\tpublic $uuid = 0;\n\tpublic $data = array();\n\tpublic $dataNodes = array();\n\tpublic $events = array();\n\tpublic $eventsNodes = array();\n\tpublic $eventsGlobal = array();\n\t/**\n\t * @TODO iframes support http://code.google.com/p/phpquery/issues/detail?id=28\n\t * @var unknown_type\n\t */\n\tpublic $frames = array();\n\t/**\n\t * Document root, by default equals to document itself.\n\t * Used by documentFragments.\n\t *\n\t * @var DOMNode\n\t */\n\tpublic $root;\n\tpublic $isDocumentFragment;\n\tpublic $isXML = false;\n\tpublic $isXHTML = false;\n\tpublic $isHTML = false;\n\tpublic $charset;\n\tpublic function __construct($markup = null, $contentType = null, $newDocumentID = null) {\n\t\tif (isset($markup))\n\t\t\t$this->load($markup, $contentType, $newDocumentID);\n\t\t$this->id = $newDocumentID\n\t\t\t? $newDocumentID\n\t\t\t: md5(microtime());\n\t}\n\tpublic function load($markup, $contentType = null, $newDocumentID = null) {\n//\t\tphpQuery::$documents[$id] = $this;\n\t\t$this->contentType = strtolower($contentType);\n\t\tif ($markup instanceof DOMDOCUMENT) {\n\t\t\t$this->document = $markup;\n\t\t\t$this->root = $this->document;\n\t\t\t$this->charset = $this->document->encoding;\n\t\t\t// TODO isDocumentFragment\n\t\t\t$loaded = true;\n\t\t} else {\n\t\t\t$loaded = $this->loadMarkup($markup);\n\t\t}\n\t\tif ($loaded) {\n//\t\t\t$this->document->formatOutput = true;\n\t\t\t$this->document->preserveWhiteSpace = true;\n\t\t\t$this->xpath = new DOMXPath($this->document);\n\t\t\t$this->afterMarkupLoad();\n\t\t\treturn true;\n\t\t\t// remember last loaded document\n//\t\t\treturn phpQuery::selectDocument($id);\n\t\t}\n\t\treturn false;\n\t}\n\tprotected function afterMarkupLoad() {\n\t\tif ($this->isXHTML) {\n\t\t\t$this->xpath->registerNamespace(\"html\", \"http://www.w3.org/1999/xhtml\");\n\t\t}\n\t}\n\tprotected function loadMarkup($markup) {\n\t\t$loaded = false;\n\t\tif ($this->contentType) {\n\t\t\tself::debug(\"Load markup for content type {$this->contentType}\");\n\t\t\t// content determined by contentType\n\t\t\tlist($contentType, $charset) = $this->contentTypeToArray($this->contentType);\n\t\t\tswitch($contentType) {\n\t\t\t\tcase 'text/html':\n\t\t\t\t\tphpQuery::debug(\"Loading HTML, content type '{$this->contentType}'\");\n\t\t\t\t\t$loaded = $this->loadMarkupHTML($markup, $charset);\n\t\t\t\tbreak;\n\t\t\t\tcase 'text/xml':\n\t\t\t\tcase 'application/xhtml+xml':\n\t\t\t\t\tphpQuery::debug(\"Loading XML, content type '{$this->contentType}'\");\n\t\t\t\t\t$loaded = $this->loadMarkupXML($markup, $charset);\n\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// for feeds or anything that sometimes doesn't use text/xml\n\t\t\t\t\tif (strpos('xml', $this->contentType) !== false) {\n\t\t\t\t\t\tphpQuery::debug(\"Loading XML, content type '{$this->contentType}'\");\n\t\t\t\t\t\t$loaded = $this->loadMarkupXML($markup, $charset);\n\t\t\t\t\t} else\n\t\t\t\t\t\tphpQuery::debug(\"Could not determine document type from content type '{$this->contentType}'\");\n\t\t\t}\n\t\t} else {\n\t\t\t// content type autodetection\n\t\t\tif ($this->isXML($markup)) {\n\t\t\t\tphpQuery::debug(\"Loading XML, isXML() == true\");\n\t\t\t\t$loaded = $this->loadMarkupXML($markup);\n\t\t\t\tif (! $loaded && $this->isXHTML) {\n\t\t\t\t\tphpQuery::debug('Loading as XML failed, trying to load as HTML, isXHTML == true');\n\t\t\t\t\t$loaded = $this->loadMarkupHTML($markup);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tphpQuery::debug(\"Loading HTML, isXML() == false\");\n\t\t\t\t$loaded = $this->loadMarkupHTML($markup);\n\t\t\t}\n\t\t}\n\t\treturn $loaded;\n\t}\n\tprotected function loadMarkupReset() {\n\t\t$this->isXML = $this->isXHTML = $this->isHTML = false;\n\t}\n\tprotected function documentCreate($charset, $version = '1.0') {\n\t\tif (! $version)\n\t\t\t$version = '1.0';\n\t\t$this->document = new DOMDocument($version, $charset);\n\t\t$this->charset = $this->document->encoding;\n//\t\t$this->document->encoding = $charset;\n\t\t$this->document->formatOutput = true;\n\t\t$this->document->preserveWhiteSpace = true;\n\t}\n\tprotected function loadMarkupHTML($markup, $requestedCharset = null) {\n\t\tif (phpQuery::$debug)\n\t\t\tphpQuery::debug('Full markup load (HTML): '.substr($markup, 0, 250));\n\t\t$this->loadMarkupReset();\n\t\t$this->isHTML = true;\n\t\tif (!isset($this->isDocumentFragment))\n\t\t\t$this->isDocumentFragment = self::isDocumentFragmentHTML($markup);\n\t\t$charset = null;\n\t\t$documentCharset = $this->charsetFromHTML($markup);\n\t\t$addDocumentCharset = false;\n\t\tif ($documentCharset) {\n\t\t\t$charset = $documentCharset;\n\t\t\t$markup = $this->charsetFixHTML($markup);\n\t\t} else if ($requestedCharset) {\n\t\t\t$charset = $requestedCharset;\n\t\t}\n\t\tif (! $charset)\n\t\t\t$charset = phpQuery::$defaultCharset;\n\t\t// HTTP 1.1 says that the default charset is ISO-8859-1\n\t\t// @see http://www.w3.org/International/O-HTTP-charset\n\t\tif (! $documentCharset) {\n\t\t\t$documentCharset = 'ISO-8859-1';\n\t\t\t$addDocumentCharset = true;\n\t\t}\n\t\t// Should be careful here, still need 'magic encoding detection' since lots of pages have other 'default encoding'\n\t\t// Worse, some pages can have mixed encodings... we'll try not to worry about that\n\t\t$requestedCharset = strtoupper($requestedCharset);\n\t\t$documentCharset = strtoupper($documentCharset);\n\t\tphpQuery::debug(\"DOC: $documentCharset REQ: $requestedCharset\");\n\t\tif ($requestedCharset && $documentCharset && $requestedCharset !== $documentCharset) {\n\t\t\tphpQuery::debug(\"CHARSET CONVERT\");\n\t\t\t// Document Encoding Conversion\n\t\t\t// http://code.google.com/p/phpquery/issues/detail?id=86\n\t\t\tif (function_exists('mb_detect_encoding')) {\n\t\t\t\t$possibleCharsets = array($documentCharset, $requestedCharset, 'AUTO');\n\t\t\t\t$docEncoding = mb_detect_encoding($markup, implode(', ', $possibleCharsets));\n\t\t\t\tif (! $docEncoding)\n\t\t\t\t\t$docEncoding = $documentCharset; // ok trust the document\n\t\t\t\tphpQuery::debug(\"DETECTED '$docEncoding'\");\n\t\t\t\t// Detected does not match what document says...\n\t\t\t\tif ($docEncoding !== $documentCharset) {\n\t\t\t\t\t// Tricky..\n\t\t\t\t}\n\t\t\t\tif ($docEncoding !== $requestedCharset) {\n\t\t\t\t\tphpQuery::debug(\"CONVERT $docEncoding => $requestedCharset\");\n\t\t\t\t\t$markup = mb_convert_encoding($markup, $requestedCharset, $docEncoding);\n\t\t\t\t\t$markup = $this->charsetAppendToHTML($markup, $requestedCharset);\n\t\t\t\t\t$charset = $requestedCharset;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tphpQuery::debug(\"TODO: charset conversion without mbstring...\");\n\t\t\t}\n\t\t}\n\t\t$return = false;\n\t\tif ($this->isDocumentFragment) {\n\t\t\tphpQuery::debug(\"Full markup load (HTML), DocumentFragment detected, using charset '$charset'\");\n\t\t\t$return = $this->documentFragmentLoadMarkup($this, $charset, $markup);\n\t\t} else {\n\t\t\tif ($addDocumentCharset) {\n\t\t\t\tphpQuery::debug(\"Full markup load (HTML), appending charset: '$charset'\");\n\t\t\t\t$markup = $this->charsetAppendToHTML($markup, $charset);\n\t\t\t}\n\t\t\tphpQuery::debug(\"Full markup load (HTML), documentCreate('$charset')\");\n\t\t\t$this->documentCreate($charset);\n\t\t\t$return = phpQuery::$debug === 2\n\t\t\t\t? $this->document->loadHTML($markup)\n\t\t\t\t: @$this->document->loadHTML($markup);\n\t\t\tif ($return)\n\t\t\t\t$this->root = $this->document;\n\t\t}\n\t\tif ($return && ! $this->contentType)\n\t\t\t$this->contentType = 'text/html';\n\t\treturn $return;\n\t}\n\tprotected function loadMarkupXML($markup, $requestedCharset = null) {\n\t\tif (phpQuery::$debug)\n\t\t\tphpQuery::debug('Full markup load (XML): '.substr($markup, 0, 250));\n\t\t$this->loadMarkupReset();\n\t\t$this->isXML = true;\n\t\t// check agains XHTML in contentType or markup\n\t\t$isContentTypeXHTML = $this->isXHTML();\n\t\t$isMarkupXHTML = $this->isXHTML($markup);\n\t\tif ($isContentTypeXHTML || $isMarkupXHTML) {\n\t\t\tself::debug('Full markup load (XML), XHTML detected');\n\t\t\t$this->isXHTML = true;\n\t\t}\n\t\t// determine document fragment\n\t\tif (! isset($this->isDocumentFragment))\n\t\t\t$this->isDocumentFragment = $this->isXHTML\n\t\t\t\t? self::isDocumentFragmentXHTML($markup)\n\t\t\t\t: self::isDocumentFragmentXML($markup);\n\t\t// this charset will be used\n\t\t$charset = null;\n\t\t// charset from XML declaration @var string\n\t\t$documentCharset = $this->charsetFromXML($markup);\n\t\tif (! $documentCharset) {\n\t\t\tif ($this->isXHTML) {\n\t\t\t\t// this is XHTML, try to get charset from content-type meta header\n\t\t\t\t$documentCharset = $this->charsetFromHTML($markup);\n\t\t\t\tif ($documentCharset) {\n\t\t\t\t\tphpQuery::debug(\"Full markup load (XML), appending XHTML charset '$documentCharset'\");\n\t\t\t\t\t$this->charsetAppendToXML($markup, $documentCharset);\n\t\t\t\t\t$charset = $documentCharset;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (! $documentCharset) {\n\t\t\t\t// if still no document charset...\n\t\t\t\t$charset = $requestedCharset;\n\t\t\t}\n\t\t} else if ($requestedCharset) {\n\t\t\t$charset = $requestedCharset;\n\t\t}\n\t\tif (! $charset) {\n\t\t\t$charset = phpQuery::$defaultCharset;\n\t\t}\n\t\tif ($requestedCharset && $documentCharset && $requestedCharset != $documentCharset) {\n\t\t\t// TODO place for charset conversion\n//\t\t\t$charset = $requestedCharset;\n\t\t}\n\t\t$return = false;\n\t\tif ($this->isDocumentFragment) {\n\t\t\tphpQuery::debug(\"Full markup load (XML), DocumentFragment detected, using charset '$charset'\");\n\t\t\t$return = $this->documentFragmentLoadMarkup($this, $charset, $markup);\n\t\t} else {\n\t\t\t// FIXME ???\n\t\t\tif ($isContentTypeXHTML && ! $isMarkupXHTML)\n\t\t\tif (! $documentCharset) {\n\t\t\t\tphpQuery::debug(\"Full markup load (XML), appending charset '$charset'\");\n\t\t\t\t$markup = $this->charsetAppendToXML($markup, $charset);\n\t\t\t}\n\t\t\t// see http://pl2.php.net/manual/en/book.dom.php#78929\n\t\t\t// LIBXML_DTDLOAD (>= PHP 5.1)\n\t\t\t// does XML ctalogues works with LIBXML_NONET\n\t//\t\t$this->document->resolveExternals = true;\n\t\t\t// TODO test LIBXML_COMPACT for performance improvement\n\t\t\t// create document\n\t\t\t$this->documentCreate($charset);\n\t\t\tif (phpversion() < 5.1) {\n\t\t\t\t$this->document->resolveExternals = true;\n\t\t\t\t$return = phpQuery::$debug === 2\n\t\t\t\t\t? $this->document->loadXML($markup)\n\t\t\t\t\t: @$this->document->loadXML($markup);\n\t\t\t} else {\n\t\t\t\t/** @link http://pl2.php.net/manual/en/libxml.constants.php */\n\t\t\t\t$libxmlStatic = phpQuery::$debug === 2\n\t\t\t\t\t? LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET\n\t\t\t\t\t: LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET|LIBXML_NOWARNING|LIBXML_NOERROR;\n\t\t\t\t$return = $this->document->loadXML($markup, $libxmlStatic);\n// \t\t\t\tif (! $return)\n// \t\t\t\t\t$return = $this->document->loadHTML($markup);\n\t\t\t}\n\t\t\tif ($return)\n\t\t\t\t$this->root = $this->document;\n\t\t}\n\t\tif ($return) {\n\t\t\tif (! $this->contentType) {\n\t\t\t\tif ($this->isXHTML)\n\t\t\t\t\t$this->contentType = 'application/xhtml+xml';\n\t\t\t\telse\n\t\t\t\t\t$this->contentType = 'text/xml';\n\t\t\t}\n\t\t\treturn $return;\n\t\t} else {\n\t\t\tthrow new Exception(\"Error loading XML markup\");\n\t\t}\n\t}\n\tprotected function isXHTML($markup = null) {\n\t\tif (! isset($markup)) {\n\t\t\treturn strpos($this->contentType, 'xhtml') !== false;\n\t\t}\n\t\t// XXX ok ?\n\t\treturn strpos($markup, \"<!DOCTYPE html\") !== false;\n//\t\treturn stripos($doctype, 'xhtml') !== false;\n//\t\t$doctype = isset($dom->doctype) && is_object($dom->doctype)\n//\t\t\t? $dom->doctype->publicId\n//\t\t\t: self::$defaultDoctype;\n\t}\n\tprotected function isXML($markup) {\n//\t\treturn strpos($markup, '<?xml') !== false && stripos($markup, 'xhtml') === false;\n\t\treturn strpos(substr($markup, 0, 100), '<'.'?xml') !== false;\n\t}\n\tprotected function contentTypeToArray($contentType) {\n\t\t$matches = explode(';', trim(strtolower($contentType)));\n\t\tif (isset($matches[1])) {\n\t\t\t$matches[1] = explode('=', $matches[1]);\n\t\t\t// strip 'charset='\n\t\t\t$matches[1] = isset($matches[1][1]) && trim($matches[1][1])\n\t\t\t\t? $matches[1][1]\n\t\t\t\t: $matches[1][0];\n\t\t} else\n\t\t\t$matches[1] = null;\n\t\treturn $matches;\n\t}\n\t/**\n\t *\n\t * @param $markup\n\t * @return array contentType, charset\n\t */\n\tprotected function contentTypeFromHTML($markup) {\n\t\t$matches = array();\n\t\t// find meta tag\n\t\tpreg_match('@<meta[^>]+http-equiv\\\\s*=\\\\s*([\"|\\'])Content-Type\\\\1([^>]+?)>@i',\n\t\t\t$markup, $matches\n\t\t);\n\t\tif (! isset($matches[0]))\n\t\t\treturn array(null, null);\n\t\t// get attr 'content'\n\t\tpreg_match('@content\\\\s*=\\\\s*([\"|\\'])(.+?)\\\\1@', $matches[0], $matches);\n\t\tif (! isset($matches[0]))\n\t\t\treturn array(null, null);\n\t\treturn $this->contentTypeToArray($matches[2]);\n\t}\n\tprotected function charsetFromHTML($markup) {\n\t\t$contentType = $this->contentTypeFromHTML($markup);\n\t\treturn $contentType[1];\n\t}\n\tprotected function charsetFromXML($markup) {\n\t\t$matches;\n\t\t// find declaration\n\t\tpreg_match('@<'.'?xml[^>]+encoding\\\\s*=\\\\s*([\"|\\'])(.*?)\\\\1@i',\n\t\t\t$markup, $matches\n\t\t);\n\t\treturn isset($matches[2])\n\t\t\t? strtolower($matches[2])\n\t\t\t: null;\n\t}\n\t/**\n\t * Repositions meta[type=charset] at the start of head. Bypasses DOMDocument bug.\n\t *\n\t * @link http://code.google.com/p/phpquery/issues/detail?id=80\n\t * @param $html\n\t */\n\tprotected function charsetFixHTML($markup) {\n\t\t$matches = array();\n\t\t// find meta tag\n\t\tpreg_match('@\\s*<meta[^>]+http-equiv\\\\s*=\\\\s*([\"|\\'])Content-Type\\\\1([^>]+?)>@i',\n\t\t\t$markup, $matches, PREG_OFFSET_CAPTURE\n\t\t);\n\t\tif (! isset($matches[0]))\n\t\t\treturn;\n\t\t$metaContentType = $matches[0][0];\n\t\t$markup = substr($markup, 0, $matches[0][1])\n\t\t\t.substr($markup, $matches[0][1]+strlen($metaContentType));\n\t\t$headStart = stripos($markup, '<head>');\n\t\t$markup = substr($markup, 0, $headStart+6).$metaContentType\n\t\t\t.substr($markup, $headStart+6);\n\t\treturn $markup;\n\t}\n\tprotected function charsetAppendToHTML($html, $charset, $xhtml = false) {\n\t\t// remove existing meta[type=content-type]\n\t\t$html = preg_replace('@\\s*<meta[^>]+http-equiv\\\\s*=\\\\s*([\"|\\'])Content-Type\\\\1([^>]+?)>@i', '', $html);\n\t\t$meta = '<meta http-equiv=\"Content-Type\" content=\"text/html;charset='\n\t\t\t.$charset.'\" '\n\t\t\t.($xhtml ? '/' : '')\n\t\t\t.'>';\n\t\tif (strpos($html, '<head') === false) {\n\t\t\tif (strpos($html, '<html') === false) {\n\t\t\t\treturn $meta.$html;\n\t\t\t} else {\n\t\t\t\treturn preg_replace(\n\t\t\t\t\t'@<html(.*?)(?(?<!\\?)>)@s',\n\t\t\t\t\t\"<html\\\\1><head>{$meta}</head>\",\n\t\t\t\t\t$html\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\treturn preg_replace(\n\t\t\t\t'@<head(.*?)(?(?<!\\?)>)@s',\n\t\t\t\t'<head\\\\1>'.$meta,\n\t\t\t\t$html\n\t\t\t);\n\t\t}\n\t}\n\tprotected function charsetAppendToXML($markup, $charset) {\n\t\t$declaration = '<'.'?xml version=\"1.0\" encoding=\"'.$charset.'\"?'.'>';\n\t\treturn $declaration.$markup;\n\t}\n\tpublic static function isDocumentFragmentHTML($markup) {\n\t\treturn stripos($markup, '<html') === false && stripos($markup, '<!doctype') === false;\n\t}\n\tpublic static function isDocumentFragmentXML($markup) {\n\t\treturn stripos($markup, '<'.'?xml') === false;\n\t}\n\tpublic static function isDocumentFragmentXHTML($markup) {\n\t\treturn self::isDocumentFragmentHTML($markup);\n\t}\n\tpublic function importAttr($value) {\n\t\t// TODO\n\t}\n\t/**\n\t *\n\t * @param $source\n\t * @param $target\n\t * @param $sourceCharset\n\t * @return array Array of imported nodes.\n\t */\n\tpublic function import($source, $sourceCharset = null) {\n\t\t// TODO charset conversions\n\t\t$return = array();\n\t\tif ($source instanceof DOMNODE && !($source instanceof DOMNODELIST))\n\t\t\t$source = array($source);\n//\t\tif (is_array($source)) {\n//\t\t\tforeach($source as $node) {\n//\t\t\t\tif (is_string($node)) {\n//\t\t\t\t\t// string markup\n//\t\t\t\t\t$fake = $this->documentFragmentCreate($node, $sourceCharset);\n//\t\t\t\t\tif ($fake === false)\n//\t\t\t\t\t\tthrow new Exception(\"Error loading documentFragment markup\");\n//\t\t\t\t\telse\n//\t\t\t\t\t\t$return = array_merge($return,\n//\t\t\t\t\t\t\t$this->import($fake->root->childNodes)\n//\t\t\t\t\t\t);\n//\t\t\t\t} else {\n//\t\t\t\t\t$return[] = $this->document->importNode($node, true);\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\treturn $return;\n//\t\t} else {\n//\t\t\t// string markup\n//\t\t\t$fake = $this->documentFragmentCreate($source, $sourceCharset);\n//\t\t\tif ($fake === false)\n//\t\t\t\tthrow new Exception(\"Error loading documentFragment markup\");\n//\t\t\telse\n//\t\t\t\treturn $this->import($fake->root->childNodes);\n//\t\t}\n\t\tif (is_array($source) || $source instanceof DOMNODELIST) {\n\t\t\t// dom nodes\n\t\t\tself::debug('Importing nodes to document');\n\t\t\tforeach($source as $node)\n\t\t\t\t$return[] = $this->document->importNode($node, true);\n\t\t} else {\n\t\t\t// string markup\n\t\t\t$fake = $this->documentFragmentCreate($source, $sourceCharset);\n\t\t\tif ($fake === false)\n\t\t\t\tthrow new Exception(\"Error loading documentFragment markup\");\n\t\t\telse\n\t\t\t\treturn $this->import($fake->root->childNodes);\n\t\t}\n\t\treturn $return;\n\t}\n\t/**\n\t * Creates new document fragment.\n\t *\n\t * @param $source\n\t * @return DOMDocumentWrapper\n\t */\n\tprotected function documentFragmentCreate($source, $charset = null) {\n\t\t$fake = new DOMDocumentWrapper();\n\t\t$fake->contentType = $this->contentType;\n\t\t$fake->isXML = $this->isXML;\n\t\t$fake->isHTML = $this->isHTML;\n\t\t$fake->isXHTML = $this->isXHTML;\n\t\t$fake->root = $fake->document;\n\t\tif (! $charset)\n\t\t\t$charset = $this->charset;\n//\t$fake->documentCreate($this->charset);\n\t\tif ($source instanceof DOMNODE && !($source instanceof DOMNODELIST))\n\t\t\t$source = array($source);\n\t\tif (is_array($source) || $source instanceof DOMNODELIST) {\n\t\t\t// dom nodes\n\t\t\t// load fake document\n\t\t\tif (! $this->documentFragmentLoadMarkup($fake, $charset))\n\t\t\t\treturn false;\n\t\t\t$nodes = $fake->import($source);\n\t\t\tforeach($nodes as $node)\n\t\t\t\t$fake->root->appendChild($node);\n\t\t} else {\n\t\t\t// string markup\n\t\t\t$this->documentFragmentLoadMarkup($fake, $charset, $source);\n\t\t}\n\t\treturn $fake;\n\t}\n\t/**\n\t *\n\t * @param $document DOMDocumentWrapper\n\t * @param $markup\n\t * @return $document\n\t */\n\tprivate function documentFragmentLoadMarkup($fragment, $charset, $markup = null) {\n\t\t// TODO error handling\n\t\t// TODO copy doctype\n\t\t// tempolary turn off\n\t\t$fragment->isDocumentFragment = false;\n\t\tif ($fragment->isXML) {\n\t\t\tif ($fragment->isXHTML) {\n\t\t\t\t// add FAKE element to set default namespace\n\t\t\t\t$fragment->loadMarkupXML('<?xml version=\"1.0\" encoding=\"'.$charset.'\"?>'\n\t\t\t\t\t.'<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" '\n\t\t\t\t\t.'\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">'\n\t\t\t\t\t.'<fake xmlns=\"http://www.w3.org/1999/xhtml\">'.$markup.'</fake>');\n\t\t\t\t$fragment->root = $fragment->document->firstChild->nextSibling;\n\t\t\t} else {\n\t\t\t\t$fragment->loadMarkupXML('<?xml version=\"1.0\" encoding=\"'.$charset.'\"?><fake>'.$markup.'</fake>');\n\t\t\t\t$fragment->root = $fragment->document->firstChild;\n\t\t\t}\n\t\t} else {\n\t\t\t$markup2 = phpQuery::$defaultDoctype.'<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset='\n\t\t\t\t.$charset.'\"></head>';\n\t\t\t$noBody = strpos($markup, '<body') === false;\n\t\t\tif ($noBody)\n\t\t\t\t$markup2 .= '<body>';\n\t\t\t$markup2 .= $markup;\n\t\t\tif ($noBody)\n\t\t\t\t$markup2 .= '</body>';\n\t\t\t$markup2 .= '</html>';\n\t\t\t$fragment->loadMarkupHTML($markup2);\n\t\t\t// TODO resolv body tag merging issue\n\t\t\t$fragment->root = $noBody\n\t\t\t\t? $fragment->document->firstChild->nextSibling->firstChild->nextSibling\n\t\t\t\t: $fragment->document->firstChild->nextSibling->firstChild->nextSibling;\n\t\t}\n\t\tif (! $fragment->root)\n\t\t\treturn false;\n\t\t$fragment->isDocumentFragment = true;\n\t\treturn true;\n\t}\n\tprotected function documentFragmentToMarkup($fragment) {\n\t\tphpQuery::debug('documentFragmentToMarkup');\n\t\t$tmp = $fragment->isDocumentFragment;\n\t\t$fragment->isDocumentFragment = false;\n\t\t$markup = $fragment->markup();\n\t\tif ($fragment->isXML) {\n\t\t\t$markup = substr($markup, 0, strrpos($markup, '</fake>'));\n\t\t\tif ($fragment->isXHTML) {\n\t\t\t\t$markup = substr($markup, strpos($markup, '<fake')+43);\n\t\t\t} else {\n\t\t\t\t$markup = substr($markup, strpos($markup, '<fake>')+6);\n\t\t\t}\n\t\t} else {\n\t\t\t\t$markup = substr($markup, strpos($markup, '<body>')+6);\n\t\t\t\t$markup = substr($markup, 0, strrpos($markup, '</body>'));\n\t\t}\n\t\t$fragment->isDocumentFragment = $tmp;\n\t\tif (phpQuery::$debug)\n\t\t\tphpQuery::debug('documentFragmentToMarkup: '.substr($markup, 0, 150));\n\t\treturn $markup;\n\t}\n\t/**\n\t * Return document markup, starting with optional $nodes as root.\n\t *\n\t * @param $nodes\tDOMNode|DOMNodeList\n\t * @return string\n\t */\n\tpublic function markup($nodes = null, $innerMarkup = false) {\n\t\tif (isset($nodes) && count($nodes) == 1 && $nodes[0] instanceof DOMDOCUMENT)\n\t\t\t$nodes = null;\n\t\tif (isset($nodes)) {\n\t\t\t$markup = '';\n\t\t\tif (!is_array($nodes) && !($nodes instanceof DOMNODELIST) )\n\t\t\t\t$nodes = array($nodes);\n\t\t\tif ($this->isDocumentFragment && ! $innerMarkup)\n\t\t\t\tforeach($nodes as $i => $node)\n\t\t\t\t\tif ($node->isSameNode($this->root)) {\n\t\t\t\t\t//\tvar_dump($node);\n\t\t\t\t\t\t$nodes = array_slice($nodes, 0, $i)\n\t\t\t\t\t\t\t+ phpQuery::DOMNodeListToArray($node->childNodes)\n\t\t\t\t\t\t\t+ array_slice($nodes, $i+1);\n\t\t\t\t\t\t}\n\t\t\tif ($this->isXML && ! $innerMarkup) {\n\t\t\t\tself::debug(\"Getting outerXML with charset '{$this->charset}'\");\n\t\t\t\t// we need outerXML, so we can benefit from\n\t\t\t\t// $node param support in saveXML()\n\t\t\t\tforeach($nodes as $node)\n\t\t\t\t\t$markup .= $this->document->saveXML($node);\n\t\t\t} else {\n\t\t\t\t$loop = array();\n\t\t\t\tif ($innerMarkup)\n\t\t\t\t\tforeach($nodes as $node) {\n\t\t\t\t\t\tif ($node->childNodes)\n\t\t\t\t\t\t\tforeach($node->childNodes as $child)\n\t\t\t\t\t\t\t\t$loop[] = $child;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$loop[] = $node;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t$loop = $nodes;\n\t\t\t\tself::debug(\"Getting markup, moving selected nodes (\".count($loop).\") to new DocumentFragment\");\n\t\t\t\t$fake = $this->documentFragmentCreate($loop);\n\t\t\t\t$markup = $this->documentFragmentToMarkup($fake);\n\t\t\t}\n\t\t\tif ($this->isXHTML) {\n\t\t\t\tself::debug(\"Fixing XHTML\");\n\t\t\t\t$markup = self::markupFixXHTML($markup);\n\t\t\t}\n\t\t\tself::debug(\"Markup: \".substr($markup, 0, 250));\n\t\t\treturn $markup;\n\t\t} else {\n\t\t\tif ($this->isDocumentFragment) {\n\t\t\t\t// documentFragment, html only...\n\t\t\t\tself::debug(\"Getting markup, DocumentFragment detected\");\n//\t\t\t\treturn $this->markup(\n////\t\t\t\t\t$this->document->getElementsByTagName('body')->item(0)\n//\t\t\t\t\t$this->document->root, true\n//\t\t\t\t);\n\t\t\t\t$markup = $this->documentFragmentToMarkup($this);\n\t\t\t\t// no need for markupFixXHTML, as it's done thought markup($nodes) method\n\t\t\t\treturn $markup;\n\t\t\t} else {\n\t\t\t\tself::debug(\"Getting markup (\".($this->isXML?'XML':'HTML').\"), final with charset '{$this->charset}'\");\n\t\t\t\t$markup = $this->isXML\n\t\t\t\t\t? $this->document->saveXML()\n\t\t\t\t\t: $this->document->saveHTML();\n\t\t\t\tif ($this->isXHTML) {\n\t\t\t\t\tself::debug(\"Fixing XHTML\");\n\t\t\t\t\t$markup = self::markupFixXHTML($markup);\n\t\t\t\t}\n\t\t\t\tself::debug(\"Markup: \".substr($markup, 0, 250));\n\t\t\t\treturn $markup;\n\t\t\t}\n\t\t}\n\t}\n\tprotected static function markupFixXHTML($markup) {\n\t\t$markup = self::expandEmptyTag('script', $markup);\n\t\t$markup = self::expandEmptyTag('select', $markup);\n\t\t$markup = self::expandEmptyTag('textarea', $markup);\n\t\treturn $markup;\n\t}\n\tpublic static function debug($text) {\n\t\tphpQuery::debug($text);\n\t}\n\t/**\n\t * expandEmptyTag\n\t *\n\t * @param $tag\n\t * @param $xml\n\t * @return unknown_type\n\t * @author mjaque at ilkebenson dot com\n\t * @link http://php.net/manual/en/domdocument.savehtml.php#81256\n\t */\n\tpublic static function expandEmptyTag($tag, $xml){\n        $indice = 0;\n        while ($indice< strlen($xml)){\n            $pos = strpos($xml, \"<$tag \", $indice);\n            if ($pos){\n                $posCierre = strpos($xml, \">\", $pos);\n                if ($xml[$posCierre-1] == \"/\"){\n                    $xml = substr_replace($xml, \"></$tag>\", $posCierre-1, 2);\n                }\n                $indice = $posCierre;\n            }\n            else break;\n        }\n        return $xml;\n\t}\n}\n\n/**\n * Event handling class.\n *\n * @author Tobiasz Cudnik\n * @package phpQuery\n * @static\n */\nabstract class phpQueryEvents {\n\t/**\n\t * Trigger a type of event on every matched element.\n\t *\n\t * @param DOMNode|phpQueryObject|string $document\n\t * @param unknown_type $type\n\t * @param unknown_type $data\n\t *\n\t * @TODO exclusive events (with !)\n\t * @TODO global events (test)\n\t * @TODO support more than event in $type (space-separated)\n\t */\n\tpublic static function trigger($document, $type, $data = array(), $node = null) {\n\t\t// trigger: function(type, data, elem, donative, extra) {\n\t\t$documentID = phpQuery::getDocumentID($document);\n\t\t$namespace = null;\n\t\tif (strpos($type, '.') !== false)\n\t\t\tlist($name, $namespace) = explode('.', $type);\n\t\telse\n\t\t\t$name = $type;\n\t\tif (! $node) {\n\t\t\tif (self::issetGlobal($documentID, $type)) {\n\t\t\t\t$pq = phpQuery::getDocument($documentID);\n\t\t\t\t// TODO check add($pq->document)\n\t\t\t\t$pq->find('*')->add($pq->document)\n\t\t\t\t\t->trigger($type, $data);\n\t\t\t}\n\t\t} else {\n\t\t\tif (isset($data[0]) && $data[0] instanceof DOMEvent) {\n\t\t\t\t$event = $data[0];\n\t\t\t\t$event->relatedTarget = $event->target;\n\t\t\t\t$event->target = $node;\n\t\t\t\t$data = array_slice($data, 1);\n\t\t\t} else {\n\t\t\t\t$event = new DOMEvent(array(\n\t\t\t\t\t'type' => $type,\n\t\t\t\t\t'target' => $node,\n\t\t\t\t\t'timeStamp' => time(),\n\t\t\t\t));\n\t\t\t}\n\t\t\t$i = 0;\n\t\t\twhile($node) {\n\t\t\t\t// TODO whois\n\t\t\t\tphpQuery::debug(\"Triggering \".($i?\"bubbled \":'').\"event '{$type}' on \"\n\t\t\t\t\t.\"node \\n\");//.phpQueryObject::whois($node).\"\\n\");\n\t\t\t\t$event->currentTarget = $node;\n\t\t\t\t$eventNode = self::getNode($documentID, $node);\n\t\t\t\tif (isset($eventNode->eventHandlers)) {\n\t\t\t\t\tforeach($eventNode->eventHandlers as $eventType => $handlers) {\n\t\t\t\t\t\t$eventNamespace = null;\n\t\t\t\t\t\tif (strpos($type, '.') !== false)\n\t\t\t\t\t\t\tlist($eventName, $eventNamespace) = explode('.', $eventType);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$eventName = $eventType;\n\t\t\t\t\t\tif ($name != $eventName)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tif ($namespace && $eventNamespace && $namespace != $eventNamespace)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tforeach($handlers as $handler) {\n\t\t\t\t\t\t\tphpQuery::debug(\"Calling event handler\\n\");\n\t\t\t\t\t\t\t$event->data = $handler['data']\n\t\t\t\t\t\t\t\t? $handler['data']\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\t$params = array_merge(array($event), $data);\n\t\t\t\t\t\t\t$return = phpQuery::callbackRun($handler['callback'], $params);\n\t\t\t\t\t\t\tif ($return === false) {\n\t\t\t\t\t\t\t\t$event->bubbles = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// to bubble or not to bubble...\n\t\t\t\tif (! $event->bubbles)\n\t\t\t\t\tbreak;\n\t\t\t\t$node = $node->parentNode;\n\t\t\t\t$i++;\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t * Binds a handler to one or more events (like click) for each matched element.\n\t * Can also bind custom events.\n\t *\n\t * @param DOMNode|phpQueryObject|string $document\n\t * @param unknown_type $type\n\t * @param unknown_type $data Optional\n\t * @param unknown_type $callback\n\t *\n\t * @TODO support '!' (exclusive) events\n\t * @TODO support more than event in $type (space-separated)\n\t * @TODO support binding to global events\n\t */\n\tpublic static function add($document, $node, $type, $data, $callback = null) {\n\t\tphpQuery::debug(\"Binding '$type' event\");\n\t\t$documentID = phpQuery::getDocumentID($document);\n//\t\tif (is_null($callback) && is_callable($data)) {\n//\t\t\t$callback = $data;\n//\t\t\t$data = null;\n//\t\t}\n\t\t$eventNode = self::getNode($documentID, $node);\n\t\tif (! $eventNode)\n\t\t\t$eventNode = self::setNode($documentID, $node);\n\t\tif (!isset($eventNode->eventHandlers[$type]))\n\t\t\t$eventNode->eventHandlers[$type] = array();\n\t\t$eventNode->eventHandlers[$type][] = array(\n\t\t\t'callback' => $callback,\n\t\t\t'data' => $data,\n\t\t);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param DOMNode|phpQueryObject|string $document\n\t * @param unknown_type $type\n\t * @param unknown_type $callback\n\t *\n\t * @TODO namespace events\n\t * @TODO support more than event in $type (space-separated)\n\t */\n\tpublic static function remove($document, $node, $type = null, $callback = null) {\n\t\t$documentID = phpQuery::getDocumentID($document);\n\t\t$eventNode = self::getNode($documentID, $node);\n\t\tif (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) {\n\t\t\tif ($callback) {\n\t\t\t\tforeach($eventNode->eventHandlers[$type] as $k => $handler)\n\t\t\t\t\tif ($handler['callback'] == $callback)\n\t\t\t\t\t\tunset($eventNode->eventHandlers[$type][$k]);\n\t\t\t} else {\n\t\t\t\tunset($eventNode->eventHandlers[$type]);\n\t\t\t}\n\t\t}\n\t}\n\tprotected static function getNode($documentID, $node) {\n\t\tforeach(phpQuery::$documents[$documentID]->eventsNodes as $eventNode) {\n\t\t\tif ($node->isSameNode($eventNode))\n\t\t\t\treturn $eventNode;\n\t\t}\n\t}\n\tprotected static function setNode($documentID, $node) {\n\t\tphpQuery::$documents[$documentID]->eventsNodes[] = $node;\n\t\treturn phpQuery::$documents[$documentID]->eventsNodes[\n\t\t\tcount(phpQuery::$documents[$documentID]->eventsNodes)-1\n\t\t];\n\t}\n\tprotected static function issetGlobal($documentID, $type) {\n\t\treturn isset(phpQuery::$documents[$documentID])\n\t\t\t? in_array($type, phpQuery::$documents[$documentID]->eventsGlobal)\n\t\t\t: false;\n\t}\n}\n\n\ninterface ICallbackNamed {\n\tfunction hasName();\n\tfunction getName();\n}\n/**\n * Callback class introduces currying-like pattern.\n *\n * Example:\n * function foo($param1, $param2, $param3) {\n *   var_dump($param1, $param2, $param3);\n * }\n * $fooCurried = new Callback('foo',\n *   'param1 is now statically set',\n *   new CallbackParam, new CallbackParam\n * );\n * phpQuery::callbackRun($fooCurried,\n * \tarray('param2 value', 'param3 value'\n * );\n *\n * Callback class is supported in all phpQuery methods which accepts callbacks.\n *\n * @link http://code.google.com/p/phpquery/wiki/Callbacks#Param_Structures\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n *\n * @TODO??? return fake forwarding function created via create_function\n * @TODO honor paramStructure\n */\nclass Callback\n\timplements ICallbackNamed {\n\tpublic $callback = null;\n\tpublic $params = null;\n\tprotected $name;\n\tpublic function __construct($callback, $param1 = null, $param2 = null,\n\t\t\t$param3 = null) {\n\t\t$params = func_get_args();\n\t\t$params = array_slice($params, 1);\n\t\tif ($callback instanceof Callback) {\n\t\t\t// TODO implement recurention\n\t\t} else {\n\t\t\t$this->callback = $callback;\n\t\t\t$this->params = $params;\n\t\t}\n\t}\n\tpublic function getName() {\n\t\treturn 'Callback: '.$this->name;\n\t}\n\tpublic function hasName() {\n\t\treturn isset($this->name) && $this->name;\n\t}\n\tpublic function setName($name) {\n\t\t$this->name = $name;\n\t\treturn $this;\n\t}\n\t// TODO test me\n//\tpublic function addParams() {\n//\t\t$params = func_get_args();\n//\t\treturn new Callback($this->callback, $this->params+$params);\n//\t}\n}\n/**\n * Shorthand for new Callback(create_function(...), ...);\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n */\nclass CallbackBody extends Callback {\n\tpublic function __construct($paramList, $code, $param1 = null, $param2 = null,\n\t\t\t$param3 = null) {\n\t\t$params = func_get_args();\n\t\t$params = array_slice($params, 2);\n\t\t$this->callback = create_function($paramList, $code);\n\t\t$this->params = $params;\n\t}\n}\n/**\n * Callback type which on execution returns reference passed during creation.\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n */\nclass CallbackReturnReference extends Callback\n\timplements ICallbackNamed {\n\tprotected $reference;\n\tpublic function __construct(&$reference, $name = null){\n\t\t$this->reference =& $reference;\n\t\t$this->callback = array($this, 'callback');\n\t}\n\tpublic function callback() {\n\t\treturn $this->reference;\n\t}\n\tpublic function getName() {\n\t\treturn 'Callback: '.$this->name;\n\t}\n\tpublic function hasName() {\n\t\treturn isset($this->name) && $this->name;\n\t}\n}\n/**\n * Callback type which on execution returns value passed during creation.\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n */\nclass CallbackReturnValue extends Callback\n\timplements ICallbackNamed {\n\tprotected $value;\n\tprotected $name;\n\tpublic function __construct($value, $name = null){\n\t\t$this->value =& $value;\n\t\t$this->name = $name;\n\t\t$this->callback = array($this, 'callback');\n\t}\n\tpublic function callback() {\n\t\treturn $this->value;\n\t}\n\tpublic function __toString() {\n\t\treturn $this->getName();\n\t}\n\tpublic function getName() {\n\t\treturn 'Callback: '.$this->name;\n\t}\n\tpublic function hasName() {\n\t\treturn isset($this->name) && $this->name;\n\t}\n}\n/**\n * CallbackParameterToReference can be used when we don't really want a callback,\n * only parameter passed to it. CallbackParameterToReference takes first\n * parameter's value and passes it to reference.\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n */\nclass CallbackParameterToReference extends Callback {\n\t/**\n\t * @param $reference\n\t * @TODO implement $paramIndex;\n\t * param index choose which callback param will be passed to reference\n\t */\n\tpublic function __construct(&$reference){\n\t\t$this->callback =& $reference;\n\t}\n}\n//class CallbackReference extends Callback {\n//\t/**\n//\t *\n//\t * @param $reference\n//\t * @param $paramIndex\n//\t * @todo implement $paramIndex; param index choose which callback param will be passed to reference\n//\t */\n//\tpublic function __construct(&$reference, $name = null){\n//\t\t$this->callback =& $reference;\n//\t}\n//}\nclass CallbackParam {}\n\n/**\n * Class representing phpQuery objects.\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @package phpQuery\n * @method phpQueryObject clone() clone()\n * @method phpQueryObject empty() empty()\n * @method phpQueryObject next() next($selector = null)\n * @method phpQueryObject prev() prev($selector = null)\n * @property Int $length\n */\nclass phpQueryObject\n\timplements Iterator, Countable, ArrayAccess {\n\tpublic $documentID = null;\n\t/**\n\t * DOMDocument class.\n\t *\n\t * @var DOMDocument\n\t */\n\tpublic $document = null;\n\tpublic $charset = null;\n\t/**\n\t *\n\t * @var DOMDocumentWrapper\n\t */\n\tpublic $documentWrapper = null;\n\t/**\n\t * XPath interface.\n\t *\n\t * @var DOMXPath\n\t */\n\tpublic $xpath = null;\n\t/**\n\t * Stack of selected elements.\n\t * @TODO refactor to ->nodes\n\t * @var array\n\t */\n\tpublic $elements = array();\n\t/**\n\t * @access private\n\t */\n\tprotected $elementsBackup = array();\n\t/**\n\t * @access private\n\t */\n\tprotected $previous = null;\n\t/**\n\t * @access private\n\t * @TODO deprecate\n\t */\n\tprotected $root = array();\n\t/**\n\t * Indicated if doument is just a fragment (no <html> tag).\n\t *\n\t * Every document is realy a full document, so even documentFragments can\n\t * be queried against <html>, but getDocument(id)->htmlOuter() will return\n\t * only contents of <body>.\n\t *\n\t * @var bool\n\t */\n\tpublic $documentFragment = true;\n\t/**\n\t * Iterator interface helper\n\t * @access private\n\t */\n\tprotected $elementsInterator = array();\n\t/**\n\t * Iterator interface helper\n\t * @access private\n\t */\n\tprotected $valid = false;\n\t/**\n\t * Iterator interface helper\n\t * @access private\n\t */\n\tprotected $current = null;\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function __construct($documentID) {\n//\t\tif ($documentID instanceof self)\n//\t\t\tvar_dump($documentID->getDocumentID());\n\t\t$id = $documentID instanceof self\n\t\t\t? $documentID->getDocumentID()\n\t\t\t: $documentID;\n//\t\tvar_dump($id);\n\t\tif (! isset(phpQuery::$documents[$id] )) {\n//\t\t\tvar_dump(phpQuery::$documents);\n\t\t\tthrow new Exception(\"Document with ID '{$id}' isn't loaded. Use phpQuery::newDocument(\\$html) or phpQuery::newDocumentFile(\\$file) first.\");\n\t\t}\n\t\t$this->documentID = $id;\n\t\t$this->documentWrapper =& phpQuery::$documents[$id];\n\t\t$this->document =& $this->documentWrapper->document;\n\t\t$this->xpath =& $this->documentWrapper->xpath;\n\t\t$this->charset =& $this->documentWrapper->charset;\n\t\t$this->documentFragment =& $this->documentWrapper->isDocumentFragment;\n\t\t// TODO check $this->DOM->documentElement;\n//\t\t$this->root = $this->document->documentElement;\n\t\t$this->root =& $this->documentWrapper->root;\n//\t\t$this->toRoot();\n\t\t$this->elements = array($this->root);\n\t}\n\t/**\n\t *\n\t * @access private\n\t * @param $attr\n\t * @return unknown_type\n\t */\n\tpublic function __get($attr) {\n\t\tswitch($attr) {\n\t\t\t// FIXME doesnt work at all ?\n\t\t\tcase 'length':\n\t\t\t\treturn $this->size();\n\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn $this->$attr;\n\t\t}\n\t}\n\t/**\n\t * Saves actual object to $var by reference.\n\t * Useful when need to break chain.\n\t * @param phpQueryObject $var\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function toReference(&$var) {\n\t\treturn $var = $this;\n\t}\n\tpublic function documentFragment($state = null) {\n\t\tif ($state) {\n\t\t\tphpQuery::$documents[$this->getDocumentID()]['documentFragment'] = $state;\n\t\t\treturn $this;\n\t\t}\n\t\treturn $this->documentFragment;\n\t}\n\t/**\n   * @access private\n   * @TODO documentWrapper\n\t */\n\tprotected function isRoot( $node) {\n//\t\treturn $node instanceof DOMDOCUMENT || $node->tagName == 'html';\n\t\treturn $node instanceof DOMDOCUMENT\n\t\t\t|| ($node instanceof DOMELEMENT && $node->tagName == 'html')\n\t\t\t|| $this->root->isSameNode($node);\n\t}\n\t/**\n   * @access private\n\t */\n\tprotected function stackIsRoot() {\n\t\treturn $this->size() == 1 && $this->isRoot($this->elements[0]);\n\t}\n\t/**\n\t * Enter description here...\n\t * NON JQUERY METHOD\n\t *\n\t * Watch out, it doesn't creates new instance, can be reverted with end().\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function toRoot() {\n\t\t$this->elements = array($this->root);\n\t\treturn $this;\n//\t\treturn $this->newInstance(array($this->root));\n\t}\n\t/**\n\t * Saves object's DocumentID to $var by reference.\n\t * <code>\n\t * $myDocumentId;\n\t * phpQuery::newDocument('<div/>')\n\t *     ->getDocumentIDRef($myDocumentId)\n\t *     ->find('div')->...\n\t * </code>\n\t *\n\t * @param unknown_type $domId\n\t * @see phpQuery::newDocument\n\t * @see phpQuery::newDocumentFile\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function getDocumentIDRef(&$documentID) {\n\t\t$documentID = $this->getDocumentID();\n\t\treturn $this;\n\t}\n\t/**\n\t * Returns object with stack set to document root.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function getDocument() {\n\t\treturn phpQuery::getDocument($this->getDocumentID());\n\t}\n\t/**\n\t *\n\t * @return DOMDocument\n\t */\n\tpublic function getDOMDocument() {\n\t\treturn $this->document;\n\t}\n\t/**\n\t * Get object's Document ID.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function getDocumentID() {\n\t\treturn $this->documentID;\n\t}\n\t/**\n\t * Unloads whole document from memory.\n\t * CAUTION! None further operations will be possible on this document.\n\t * All objects refering to it will be useless.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function unloadDocument() {\n\t\tphpQuery::unloadDocuments($this->getDocumentID());\n\t}\n\tpublic function isHTML() {\n\t\treturn $this->documentWrapper->isHTML;\n\t}\n\tpublic function isXHTML() {\n\t\treturn $this->documentWrapper->isXHTML;\n\t}\n\tpublic function isXML() {\n\t\treturn $this->documentWrapper->isXML;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @link http://docs.jquery.com/Ajax/serialize\n\t * @return string\n\t */\n\tpublic function serialize() {\n\t\treturn phpQuery::param($this->serializeArray());\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @link http://docs.jquery.com/Ajax/serializeArray\n\t * @return array\n\t */\n\tpublic function serializeArray($submit = null) {\n\t\t$source = $this->filter('form, input, select, textarea')\n\t\t\t->find('input, select, textarea')\n\t\t\t->andSelf()\n\t\t\t->not('form');\n\t\t$return = array();\n//\t\t$source->dumpDie();\n\t\tforeach($source as $input) {\n\t\t\t$input = phpQuery::pq($input);\n\t\t\tif ($input->is('[disabled]'))\n\t\t\t\tcontinue;\n\t\t\tif (!$input->is('[name]'))\n\t\t\t\tcontinue;\n\t\t\tif ($input->is('[type=checkbox]') && !$input->is('[checked]'))\n\t\t\t\tcontinue;\n\t\t\t// jquery diff\n\t\t\tif ($submit && $input->is('[type=submit]')) {\n\t\t\t\tif ($submit instanceof DOMELEMENT && ! $input->elements[0]->isSameNode($submit))\n\t\t\t\t\tcontinue;\n\t\t\t\telse if (is_string($submit) && $input->attr('name') != $submit)\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$return[] = array(\n\t\t\t\t'name' => $input->attr('name'),\n\t\t\t\t'value' => $input->val(),\n\t\t\t);\n\t\t}\n\t\treturn $return;\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function debug($in) {\n\t\tif (! phpQuery::$debug )\n\t\t\treturn;\n\t\tprint('<pre>');\n\t\tprint_r($in);\n\t\t// file debug\n//\t\tfile_put_contents(dirname(__FILE__).'/phpQuery.log', print_r($in, true).\"\\n\", FILE_APPEND);\n\t\t// quite handy debug trace\n//\t\tif ( is_array($in))\n//\t\t\tprint_r(array_slice(debug_backtrace(), 3));\n\t\tprint(\"</pre>\\n\");\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function isRegexp($pattern) {\n\t\treturn in_array(\n\t\t\t$pattern[ mb_strlen($pattern)-1 ],\n\t\t\tarray('^','*','$')\n\t\t);\n\t}\n\t/**\n\t * Determines if $char is really a char.\n\t *\n\t * @param string $char\n\t * @return bool\n\t * @todo rewrite me to charcode range ! ;)\n\t * @access private\n\t */\n\tprotected function isChar($char) {\n\t\treturn extension_loaded('mbstring') && phpQuery::$mbstringSupport\n\t\t\t? mb_eregi('\\w', $char)\n\t\t\t: preg_match('@\\w@', $char);\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function parseSelector($query) {\n\t\t// clean spaces\n\t\t// TODO include this inside parsing ?\n\t\t$query = trim(\n\t\t\tpreg_replace('@\\s+@', ' ',\n\t\t\t\tpreg_replace('@\\s*(>|\\\\+|~)\\s*@', '\\\\1', $query)\n\t\t\t)\n\t\t);\n\t\t$queries = array(array());\n\t\tif (! $query)\n\t\t\treturn $queries;\n\t\t$return =& $queries[0];\n\t\t$specialChars = array('>',' ');\n//\t\t$specialCharsMapping = array('/' => '>');\n\t\t$specialCharsMapping = array();\n\t\t$strlen = mb_strlen($query);\n\t\t$classChars = array('.', '-');\n\t\t$pseudoChars = array('-');\n\t\t$tagChars = array('*', '|', '-');\n\t\t// split multibyte string\n\t\t// http://code.google.com/p/phpquery/issues/detail?id=76\n\t\t$_query = array();\n\t\tfor ($i=0; $i<$strlen; $i++)\n\t\t\t$_query[] = mb_substr($query, $i, 1);\n\t\t$query = $_query;\n\t\t// it works, but i dont like it...\n\t\t$i = 0;\n\t\twhile( $i < $strlen) {\n\t\t\t$c = $query[$i];\n\t\t\t$tmp = '';\n\t\t\t// TAG\n\t\t\tif ($this->isChar($c) || in_array($c, $tagChars)) {\n\t\t\t\twhile(isset($query[$i])\n\t\t\t\t\t&& ($this->isChar($query[$i]) || in_array($query[$i], $tagChars))) {\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t$return[] = $tmp;\n\t\t\t// IDs\n\t\t\t} else if ( $c == '#') {\n\t\t\t\t$i++;\n\t\t\t\twhile( isset($query[$i]) && ($this->isChar($query[$i]) || $query[$i] == '-')) {\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t$return[] = '#'.$tmp;\n\t\t\t// SPECIAL CHARS\n\t\t\t} else if (in_array($c, $specialChars)) {\n\t\t\t\t$return[] = $c;\n\t\t\t\t$i++;\n\t\t\t// MAPPED SPECIAL MULTICHARS\n//\t\t\t} else if ( $c.$query[$i+1] == '//') {\n//\t\t\t\t$return[] = ' ';\n//\t\t\t\t$i = $i+2;\n\t\t\t// MAPPED SPECIAL CHARS\n\t\t\t} else if ( isset($specialCharsMapping[$c])) {\n\t\t\t\t$return[] = $specialCharsMapping[$c];\n\t\t\t\t$i++;\n\t\t\t// COMMA\n\t\t\t} else if ( $c == ',') {\n\t\t\t\t$queries[] = array();\n\t\t\t\t$return =& $queries[ count($queries)-1 ];\n\t\t\t\t$i++;\n\t\t\t\twhile( isset($query[$i]) && $query[$i] == ' ')\n\t\t\t\t\t$i++;\n\t\t\t// CLASSES\n\t\t\t} else if ($c == '.') {\n\t\t\t\twhile( isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $classChars))) {\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t$return[] = $tmp;\n\t\t\t// ~ General Sibling Selector\n\t\t\t} else if ($c == '~') {\n\t\t\t\t$spaceAllowed = true;\n\t\t\t\t$tmp .= $query[$i++];\n\t\t\t\twhile( isset($query[$i])\n\t\t\t\t\t&& ($this->isChar($query[$i])\n\t\t\t\t\t\t|| in_array($query[$i], $classChars)\n\t\t\t\t\t\t|| $query[$i] == '*'\n\t\t\t\t\t\t|| ($query[$i] == ' ' && $spaceAllowed)\n\t\t\t\t\t)) {\n\t\t\t\t\tif ($query[$i] != ' ')\n\t\t\t\t\t\t$spaceAllowed = false;\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t$return[] = $tmp;\n\t\t\t// + Adjacent sibling selectors\n\t\t\t} else if ($c == '+') {\n\t\t\t\t$spaceAllowed = true;\n\t\t\t\t$tmp .= $query[$i++];\n\t\t\t\twhile( isset($query[$i])\n\t\t\t\t\t&& ($this->isChar($query[$i])\n\t\t\t\t\t\t|| in_array($query[$i], $classChars)\n\t\t\t\t\t\t|| $query[$i] == '*'\n\t\t\t\t\t\t|| ($spaceAllowed && $query[$i] == ' ')\n\t\t\t\t\t)) {\n\t\t\t\t\tif ($query[$i] != ' ')\n\t\t\t\t\t\t$spaceAllowed = false;\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t$return[] = $tmp;\n\t\t\t// ATTRS\n\t\t\t} else if ($c == '[') {\n\t\t\t\t$stack = 1;\n\t\t\t\t$tmp .= $c;\n\t\t\t\twhile( isset($query[++$i])) {\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\tif ( $query[$i] == '[') {\n\t\t\t\t\t\t$stack++;\n\t\t\t\t\t} else if ( $query[$i] == ']') {\n\t\t\t\t\t\t$stack--;\n\t\t\t\t\t\tif (! $stack )\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$return[] = $tmp;\n\t\t\t\t$i++;\n\t\t\t// PSEUDO CLASSES\n\t\t\t} else if ($c == ':') {\n\t\t\t\t$stack = 1;\n\t\t\t\t$tmp .= $query[$i++];\n\t\t\t\twhile( isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $pseudoChars))) {\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t// with arguments ?\n\t\t\t\tif ( isset($query[$i]) && $query[$i] == '(') {\n\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t$stack = 1;\n\t\t\t\t\twhile( isset($query[++$i])) {\n\t\t\t\t\t\t$tmp .= $query[$i];\n\t\t\t\t\t\tif ( $query[$i] == '(') {\n\t\t\t\t\t\t\t$stack++;\n\t\t\t\t\t\t} else if ( $query[$i] == ')') {\n\t\t\t\t\t\t\t$stack--;\n\t\t\t\t\t\t\tif (! $stack )\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$return[] = $tmp;\n\t\t\t\t\t$i++;\n\t\t\t\t} else {\n\t\t\t\t\t$return[] = $tmp;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$i++;\n\t\t\t}\n\t\t}\n\t\tforeach($queries as $k => $q) {\n\t\t\tif (isset($q[0])) {\n\t\t\t\tif (isset($q[0][0]) && $q[0][0] == ':')\n\t\t\t\t\tarray_unshift($queries[$k], '*');\n\t\t\t\tif ($q[0] != '>')\n\t\t\t\t\tarray_unshift($queries[$k], ' ');\n\t\t\t}\n\t\t}\n\t\treturn $queries;\n\t}\n\t/**\n\t * Return matched DOM nodes.\n\t *\n\t * @param int $index\n\t * @return array|DOMElement Single DOMElement or array of DOMElement.\n\t */\n\tpublic function get($index = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n\t\t$return = isset($index)\n\t\t\t? (isset($this->elements[$index]) ? $this->elements[$index] : null)\n\t\t\t: $this->elements;\n\t\t// pass thou callbacks\n\t\t$args = func_get_args();\n\t\t$args = array_slice($args, 1);\n\t\tforeach($args as $callback) {\n\t\t\tif (is_array($return))\n\t\t\t\tforeach($return as $k => $v)\n\t\t\t\t\t$return[$k] = phpQuery::callbackRun($callback, array($v));\n\t\t\telse\n\t\t\t\t$return = phpQuery::callbackRun($callback, array($return));\n\t\t}\n\t\treturn $return;\n\t}\n\t/**\n\t * Return matched DOM nodes.\n\t * jQuery difference.\n\t *\n\t * @param int $index\n\t * @return array|string Returns string if $index != null\n\t * @todo implement callbacks\n\t * @todo return only arrays ?\n\t * @todo maybe other name...\n\t */\n\tpublic function getString($index = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n        if (!is_null($index) && is_int($index))\n\t\t\t$return = $this->eq($index)->text();\n\t\telse {\n\t\t\t$return = array();\n\t\t\tfor($i = 0; $i < $this->size(); $i++) {\n\t\t\t\t$return[] = $this->eq($i)->text();\n\t\t\t}\n\t\t}\n\t\t// pass thou callbacks\n\t\t$args = func_get_args();\n\t\t$args = array_slice($args, 1);\n\t\tforeach($args as $callback) {\n\t\t\t$return = phpQuery::callbackRun($callback, array($return));\n\t\t}\n\t\treturn $return;\n\t}\n\t/**\n\t * Return matched DOM nodes.\n\t * jQuery difference.\n\t *\n\t * @param int $index\n\t * @return array|string Returns string if $index != null\n\t * @todo implement callbacks\n\t * @todo return only arrays ?\n\t * @todo maybe other name...\n\t */\n\tpublic function getStrings($index = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n        if (!is_null($index) && is_int($index))\n\t\t\t$return = $this->eq($index)->text();\n\t\telse {\n\t\t\t$return = array();\n\t\t\tfor($i = 0; $i < $this->size(); $i++) {\n\t\t\t\t$return[] = $this->eq($i)->text();\n\t\t\t}\n\t\t\t// pass thou callbacks\n\t\t\t$args = func_get_args();\n\t\t\t$args = array_slice($args, 1);\n\t\t}\n\t\tforeach($args as $callback) {\n\t\t\tif (is_array($return))\n\t\t\t\tforeach($return as $k => $v)\n\t\t\t\t\t$return[$k] = phpQuery::callbackRun($callback, array($v));\n\t\t\telse\n\t\t\t\t$return = phpQuery::callbackRun($callback, array($return));\n\t\t}\n\t\treturn $return;\n\t}\n\t/**\n\t * Returns new instance of actual class.\n\t *\n\t * @param array $newStack Optional. Will replace old stack with new and move old one to history.c\n\t */\n\tpublic function newInstance($newStack = null) {\n\t\t$class = get_class($this);\n\t\t// support inheritance by passing old object to overloaded constructor\n\t\t$new = $class != 'phpQuery'\n\t\t\t? new $class($this, $this->getDocumentID())\n\t\t\t: new phpQueryObject($this->getDocumentID());\n\t\t$new->previous = $this;\n\t\tif (is_null($newStack)) {\n\t\t\t$new->elements = $this->elements;\n\t\t\tif ($this->elementsBackup)\n\t\t\t\t$this->elements = $this->elementsBackup;\n\t\t} else if (is_string($newStack)) {\n\t\t\t$new->elements = phpQuery::pq($newStack, $this->getDocumentID())->stack();\n\t\t} else {\n\t\t\t$new->elements = $newStack;\n\t\t}\n\t\treturn $new;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * In the future, when PHP will support XLS 2.0, then we would do that this way:\n\t * contains(tokenize(@class, '\\s'), \"something\")\n\t * @param unknown_type $class\n\t * @param unknown_type $node\n\t * @return boolean\n\t * @access private\n\t */\n\tprotected function matchClasses($class, $node) {\n\t\t// multi-class\n\t\tif ( mb_strpos($class, '.', 1)) {\n\t\t\t$classes = explode('.', substr($class, 1));\n\t\t\t$classesCount = count( $classes );\n\t\t\t$nodeClasses = explode(' ', $node->getAttribute('class') );\n\t\t\t$nodeClassesCount = count( $nodeClasses );\n\t\t\tif ( $classesCount > $nodeClassesCount )\n\t\t\t\treturn false;\n\t\t\t$diff = count(\n\t\t\t\tarray_diff(\n\t\t\t\t\t$classes,\n\t\t\t\t\t$nodeClasses\n\t\t\t\t)\n\t\t\t);\n\t\t\tif (! $diff )\n\t\t\t\treturn true;\n\t\t// single-class\n\t\t} else {\n\t\t\treturn in_array(\n\t\t\t\t// strip leading dot from class name\n\t\t\t\tsubstr($class, 1),\n\t\t\t\t// get classes for element as array\n\t\t\t\texplode(' ', $node->getAttribute('class') )\n\t\t\t);\n\t\t}\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function runQuery($XQuery, $selector = null, $compare = null) {\n\t\tif ($compare && ! method_exists($this, $compare))\n\t\t\treturn false;\n\t\t$stack = array();\n\t\tif (! $this->elements)\n\t\t\t$this->debug('Stack empty, skipping...');\n//\t\tvar_dump($this->elements[0]->nodeType);\n\t\t// element, document\n\t\tforeach($this->stack(array(1, 9, 13)) as $k => $stackNode) {\n\t\t\t$detachAfter = false;\n\t\t\t// to work on detached nodes we need temporary place them somewhere\n\t\t\t// thats because context xpath queries sucks ;]\n\t\t\t$testNode = $stackNode;\n\t\t\twhile ($testNode) {\n\t\t\t\tif (! $testNode->parentNode && ! $this->isRoot($testNode)) {\n\t\t\t\t\t$this->root->appendChild($testNode);\n\t\t\t\t\t$detachAfter = $testNode;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t$testNode = isset($testNode->parentNode)\n\t\t\t\t\t? $testNode->parentNode\n\t\t\t\t\t: null;\n\t\t\t}\n\t\t\t// XXX tmp ?\n\t\t\t$xpath = $this->documentWrapper->isXHTML\n\t\t\t\t? $this->getNodeXpath($stackNode, 'html')\n\t\t\t\t: $this->getNodeXpath($stackNode);\n\t\t\t// FIXME pseudoclasses-only query, support XML\n\t\t\t$query = $XQuery == '//' && $xpath == '/html[1]'\n\t\t\t\t? '//*'\n\t\t\t\t: $xpath.$XQuery;\n\t\t\t$this->debug(\"XPATH: {$query}\");\n\t\t\t// run query, get elements\n\t\t\t$nodes = $this->xpath->query($query);\n\t\t\t$this->debug(\"QUERY FETCHED\");\n\t\t\tif (! $nodes->length )\n\t\t\t\t$this->debug('Nothing found');\n\t\t\t$debug = array();\n\t\t\tforeach($nodes as $node) {\n\t\t\t\t$matched = false;\n\t\t\t\tif ( $compare) {\n\t\t\t\t\tphpQuery::$debug ?\n\t\t\t\t\t\t$this->debug(\"Found: \".$this->whois( $node ).\", comparing with {$compare}()\")\n\t\t\t\t\t\t: null;\n\t\t\t\t\t$phpQueryDebug = phpQuery::$debug;\n\t\t\t\t\tphpQuery::$debug = false;\n\t\t\t\t\t// TODO ??? use phpQuery::callbackRun()\n\t\t\t\t\tif (call_user_func_array(array($this, $compare), array($selector, $node)))\n\t\t\t\t\t\t$matched = true;\n\t\t\t\t\tphpQuery::$debug = $phpQueryDebug;\n\t\t\t\t} else {\n\t\t\t\t\t$matched = true;\n\t\t\t\t}\n\t\t\t\tif ( $matched) {\n\t\t\t\t\tif (phpQuery::$debug)\n\t\t\t\t\t\t$debug[] = $this->whois( $node );\n\t\t\t\t\t$stack[] = $node;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (phpQuery::$debug) {\n\t\t\t\t$this->debug(\"Matched \".count($debug).\": \".implode(', ', $debug));\n\t\t\t}\n\t\t\tif ($detachAfter)\n\t\t\t\t$this->root->removeChild($detachAfter);\n\t\t}\n\t\t$this->elements = $stack;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function find($selectors, $context = null, $noHistory = false) {\n\t\tif (!$noHistory)\n\t\t\t// backup last stack /for end()/\n\t\t\t$this->elementsBackup = $this->elements;\n\t\t// allow to define context\n\t\t// TODO combine code below with phpQuery::pq() context guessing code\n\t\t//   as generic function\n\t\tif ($context) {\n\t\t\tif (! is_array($context) && $context instanceof DOMELEMENT)\n\t\t\t\t$this->elements = array($context);\n\t\t\telse if (is_array($context)) {\n\t\t\t\t$this->elements = array();\n\t\t\t\tforeach ($context as $c)\n\t\t\t\t\tif ($c instanceof DOMELEMENT)\n\t\t\t\t\t\t$this->elements[] = $c;\n\t\t\t} else if ( $context instanceof self )\n\t\t\t\t$this->elements = $context->elements;\n\t\t}\n\t\t$queries = $this->parseSelector($selectors);\n\t\t$this->debug(array('FIND', $selectors, $queries));\n\t\t$XQuery = '';\n\t\t// remember stack state because of multi-queries\n\t\t$oldStack = $this->elements;\n\t\t// here we will be keeping found elements\n\t\t$stack = array();\n\t\tforeach($queries as $selector) {\n\t\t\t$this->elements = $oldStack;\n\t\t\t$delimiterBefore = false;\n\t\t\tforeach($selector as $s) {\n\t\t\t\t// TAG\n\t\t\t\t$isTag = extension_loaded('mbstring') && phpQuery::$mbstringSupport\n\t\t\t\t\t? mb_ereg_match('^[\\w|\\||-]+$', $s) || $s == '*'\n\t\t\t\t\t: preg_match('@^[\\w|\\||-]+$@', $s) || $s == '*';\n\t\t\t\tif ($isTag) {\n\t\t\t\t\tif ($this->isXML()) {\n\t\t\t\t\t\t// namespace support\n\t\t\t\t\t\tif (mb_strpos($s, '|') !== false) {\n\t\t\t\t\t\t\t$ns = $tag = null;\n\t\t\t\t\t\t\tlist($ns, $tag) = explode('|', $s);\n\t\t\t\t\t\t\t$XQuery .= \"$ns:$tag\";\n\t\t\t\t\t\t} else if ($s == '*') {\n\t\t\t\t\t\t\t$XQuery .= \"*\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$XQuery .= \"*[local-name()='$s']\";\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$XQuery .= $s;\n\t\t\t\t\t}\n\t\t\t\t// ID\n\t\t\t\t} else if ($s[0] == '#') {\n\t\t\t\t\tif ($delimiterBefore)\n\t\t\t\t\t\t$XQuery .= '*';\n\t\t\t\t\t$XQuery .= \"[@id='\".substr($s, 1).\"']\";\n\t\t\t\t// ATTRIBUTES\n\t\t\t\t} else if ($s[0] == '[') {\n\t\t\t\t\tif ($delimiterBefore)\n\t\t\t\t\t\t$XQuery .= '*';\n\t\t\t\t\t// strip side brackets\n\t\t\t\t\t$attr = trim($s, '][');\n\t\t\t\t\t$execute = false;\n\t\t\t\t\t// attr with specifed value\n\t\t\t\t\tif (mb_strpos($s, '=')) {\n\t\t\t\t\t\t$value = null;\n\t\t\t\t\t\tlist($attr, $value) = explode('=', $attr);\n\t\t\t\t\t\t$value = trim($value, \"'\\\"\");\n\t\t\t\t\t\tif ($this->isRegexp($attr)) {\n\t\t\t\t\t\t\t// cut regexp character\n\t\t\t\t\t\t\t$attr = substr($attr, 0, -1);\n\t\t\t\t\t\t\t$execute = true;\n\t\t\t\t\t\t\t$XQuery .= \"[@{$attr}]\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$XQuery .= \"[@{$attr}='{$value}']\";\n\t\t\t\t\t\t}\n\t\t\t\t\t// attr without specified value\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$XQuery .= \"[@{$attr}]\";\n\t\t\t\t\t}\n\t\t\t\t\tif ($execute) {\n\t\t\t\t\t\t$this->runQuery($XQuery, $s, 'is');\n\t\t\t\t\t\t$XQuery = '';\n\t\t\t\t\t\tif (! $this->length())\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t// CLASSES\n\t\t\t\t} else if ($s[0] == '.') {\n\t\t\t\t\t// TODO use return $this->find(\"./self::*[contains(concat(\\\" \\\",@class,\\\" \\\"), \\\" $class \\\")]\");\n\t\t\t\t\t// thx wizDom ;)\n\t\t\t\t\tif ($delimiterBefore)\n\t\t\t\t\t\t$XQuery .= '*';\n\t\t\t\t\t$XQuery .= '[@class]';\n\t\t\t\t\t$this->runQuery($XQuery, $s, 'matchClasses');\n\t\t\t\t\t$XQuery = '';\n\t\t\t\t\tif (! $this->length() )\n\t\t\t\t\t\tbreak;\n\t\t\t\t// ~ General Sibling Selector\n\t\t\t\t} else if ($s[0] == '~') {\n\t\t\t\t\t$this->runQuery($XQuery);\n\t\t\t\t\t$XQuery = '';\n\t\t\t\t\t$this->elements = $this\n\t\t\t\t\t\t->siblings(\n\t\t\t\t\t\t\tsubstr($s, 1)\n\t\t\t\t\t\t)->elements;\n\t\t\t\t\tif (! $this->length() )\n\t\t\t\t\t\tbreak;\n\t\t\t\t// + Adjacent sibling selectors\n\t\t\t\t} else if ($s[0] == '+') {\n\t\t\t\t\t// TODO /following-sibling::\n\t\t\t\t\t$this->runQuery($XQuery);\n\t\t\t\t\t$XQuery = '';\n\t\t\t\t\t$subSelector = substr($s, 1);\n\t\t\t\t\t$subElements = $this->elements;\n\t\t\t\t\t$this->elements = array();\n\t\t\t\t\tforeach($subElements as $node) {\n\t\t\t\t\t\t// search first DOMElement sibling\n\t\t\t\t\t\t$test = $node->nextSibling;\n\t\t\t\t\t\twhile($test && ! ($test instanceof DOMELEMENT))\n\t\t\t\t\t\t\t$test = $test->nextSibling;\n\t\t\t\t\t\tif ($test && $this->is($subSelector, $test))\n\t\t\t\t\t\t\t$this->elements[] = $test;\n\t\t\t\t\t}\n\t\t\t\t\tif (! $this->length() )\n\t\t\t\t\t\tbreak;\n\t\t\t\t// PSEUDO CLASSES\n\t\t\t\t} else if ($s[0] == ':') {\n\t\t\t\t\t// TODO optimization for :first :last\n\t\t\t\t\tif ($XQuery) {\n\t\t\t\t\t\t$this->runQuery($XQuery);\n\t\t\t\t\t\t$XQuery = '';\n\t\t\t\t\t}\n\t\t\t\t\tif (! $this->length())\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t$this->pseudoClasses($s);\n\t\t\t\t\tif (! $this->length())\n\t\t\t\t\t\tbreak;\n\t\t\t\t// DIRECT DESCENDANDS\n\t\t\t\t} else if ($s == '>') {\n\t\t\t\t\t$XQuery .= '/';\n\t\t\t\t\t$delimiterBefore = 2;\n\t\t\t\t// ALL DESCENDANDS\n\t\t\t\t} else if ($s == ' ') {\n\t\t\t\t\t$XQuery .= '//';\n\t\t\t\t\t$delimiterBefore = 2;\n\t\t\t\t// ERRORS\n\t\t\t\t} else {\n\t\t\t\t\tphpQuery::debug(\"Unrecognized token '$s'\");\n\t\t\t\t}\n\t\t\t\t$delimiterBefore = $delimiterBefore === 2;\n\t\t\t}\n\t\t\t// run query if any\n\t\t\tif ($XQuery && $XQuery != '//') {\n\t\t\t\t$this->runQuery($XQuery);\n\t\t\t\t$XQuery = '';\n\t\t\t}\n\t\t\tforeach($this->elements as $node)\n\t\t\t\tif (! $this->elementsContainsNode($node, $stack))\n\t\t\t\t\t$stack[] = $node;\n\t\t}\n\t\t$this->elements = $stack;\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * @todo create API for classes with pseudoselectors\n\t * @access private\n\t */\n\tprotected function pseudoClasses($class) {\n\t\t// TODO clean args parsing ?\n\t\t$class = ltrim($class, ':');\n\t\t$haveArgs = mb_strpos($class, '(');\n\t\tif ($haveArgs !== false) {\n\t\t\t$args = substr($class, $haveArgs+1, -1);\n\t\t\t$class = substr($class, 0, $haveArgs);\n\t\t}\n\t\tswitch($class) {\n\t\t\tcase 'even':\n\t\t\tcase 'odd':\n\t\t\t\t$stack = array();\n\t\t\t\tforeach($this->elements as $i => $node) {\n\t\t\t\t\tif ($class == 'even' && ($i%2) == 0)\n\t\t\t\t\t\t$stack[] = $node;\n\t\t\t\t\telse if ( $class == 'odd' && $i % 2 )\n\t\t\t\t\t\t$stack[] = $node;\n\t\t\t\t}\n\t\t\t\t$this->elements = $stack;\n\t\t\t\tbreak;\n\t\t\tcase 'eq':\n\t\t\t\t$k = intval($args);\n\t\t\t\tif ($k < 0) {\n\t\t\t\t    $this->elements = array( $this->elements[count($this->elements)+$k] );\n\t\t\t\t} else {\n\t\t\t\t    $this->elements = isset($this->elements[$k])\n\t\t\t\t\t? array($this->elements[$k])\n\t\t\t\t\t: array();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'gt':\n\t\t\t\t$this->elements = array_slice($this->elements, $args+1);\n\t\t\t\tbreak;\n\t\t\tcase 'lt':\n\t\t\t\t$this->elements = array_slice($this->elements, 0, $args+1);\n\t\t\t\tbreak;\n\t\t\tcase 'first':\n\t\t\t\tif (isset($this->elements[0]))\n\t\t\t\t\t$this->elements = array($this->elements[0]);\n\t\t\t\tbreak;\n\t\t\tcase 'last':\n\t\t\t\tif ($this->elements)\n\t\t\t\t\t$this->elements = array($this->elements[count($this->elements)-1]);\n\t\t\t\tbreak;\n\t\t\t/*case 'parent':\n\t\t\t\t$stack = array();\n\t\t\t\tforeach($this->elements as $node) {\n\t\t\t\t\tif ( $node->childNodes->length )\n\t\t\t\t\t\t$stack[] = $node;\n\t\t\t\t}\n\t\t\t\t$this->elements = $stack;\n\t\t\t\tbreak;*/\n\t\t\tcase 'contains':\n\t\t\t\t$text = trim($args, \"\\\"'\");\n\t\t\t\t$stack = array();\n\t\t\t\tforeach($this->elements as $node) {\n\t\t\t\t\tif (mb_stripos($node->textContent, $text) === false)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t$stack[] = $node;\n\t\t\t\t}\n\t\t\t\t$this->elements = $stack;\n\t\t\t\tbreak;\n\t\t\tcase 'not':\n\t\t\t\t$selector = self::unQuote($args);\n\t\t\t\t$this->elements = $this->not($selector)->stack();\n\t\t\t\tbreak;\n\t\t\tcase 'slice':\n\t\t\t\t// TODO jQuery difference ?\n\t\t\t\t$args = explode(',',\n\t\t\t\t\tstr_replace(', ', ',', trim($args, \"\\\"'\"))\n\t\t\t\t);\n\t\t\t\t$start = $args[0];\n\t\t\t\t$end = isset($args[1])\n\t\t\t\t\t? $args[1]\n\t\t\t\t\t: null;\n\t\t\t\tif ($end > 0)\n\t\t\t\t\t$end = $end-$start;\n\t\t\t\t$this->elements = array_slice($this->elements, $start, $end);\n\t\t\t\tbreak;\n\t\t\tcase 'has':\n\t\t\t\t$selector = trim($args, \"\\\"'\");\n\t\t\t\t$stack = array();\n\t\t\t\tforeach($this->stack(1) as $el) {\n\t\t\t\t\tif ($this->find($selector, $el, true)->length)\n\t\t\t\t\t\t$stack[] = $el;\n\t\t\t\t}\n\t\t\t\t$this->elements = $stack;\n\t\t\t\tbreak;\n\t\t\tcase 'submit':\n\t\t\tcase 'reset':\n\t\t\t\t$this->elements = phpQuery::merge(\n\t\t\t\t\t$this->map(array($this, 'is'),\n\t\t\t\t\t\t\"input[type=$class]\", new CallbackParam()\n\t\t\t\t\t),\n\t\t\t\t\t$this->map(array($this, 'is'),\n\t\t\t\t\t\t\"button[type=$class]\", new CallbackParam()\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\tbreak;\n//\t\t\t\t$stack = array();\n//\t\t\t\tforeach($this->elements as $node)\n//\t\t\t\t\tif ($node->is('input[type=submit]') || $node->is('button[type=submit]'))\n//\t\t\t\t\t\t$stack[] = $el;\n//\t\t\t\t$this->elements = $stack;\n\t\t\tcase 'input':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tarray($this, 'is'),\n\t\t\t\t\t'input', new CallbackParam()\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'password':\n\t\t\tcase 'checkbox':\n\t\t\tcase 'radio':\n\t\t\tcase 'hidden':\n\t\t\tcase 'image':\n\t\t\tcase 'file':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tarray($this, 'is'),\n\t\t\t\t\t\"input[type=$class]\", new CallbackParam()\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'parent':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\treturn $node instanceof DOMELEMENT && $node->childNodes->length\n\t\t\t\t\t\t\t? $node : null;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'empty':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\treturn $node instanceof DOMELEMENT && $node->childNodes->length\n\t\t\t\t\t\t\t? null : $node;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'disabled':\n\t\t\tcase 'selected':\n\t\t\tcase 'checked':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tarray($this, 'is'),\n\t\t\t\t\t\"[$class]\", new CallbackParam()\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'enabled':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\treturn pq($node)->not(\":disabled\") ? $node : null;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'header':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\t$isHeader = isset($node->tagName) && in_array($node->tagName, array(\n\t\t\t\t\t\t\t\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"h7\"\n\t\t\t\t\t\t));\n\t\t\t\t\t\treturn $isHeader\n\t\t\t\t\t\t\t? $node\n\t\t\t\t\t\t\t: null;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n//\t\t\t\t$this->elements = $this->map(\n//\t\t\t\t\tcreate_function('$node', '$node = pq($node);\n//\t\t\t\t\t\treturn $node->is(\"h1\")\n//\t\t\t\t\t\t\t|| $node->is(\"h2\")\n//\t\t\t\t\t\t\t|| $node->is(\"h3\")\n//\t\t\t\t\t\t\t|| $node->is(\"h4\")\n//\t\t\t\t\t\t\t|| $node->is(\"h5\")\n//\t\t\t\t\t\t\t|| $node->is(\"h6\")\n//\t\t\t\t\t\t\t|| $node->is(\"h7\")\n//\t\t\t\t\t\t\t? $node\n//\t\t\t\t\t\t\t: null;')\n//\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'only-child':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\treturn pq($node)->siblings()->size() == 0 ? $node : null;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'first-child':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\treturn pq($node)->prevAll()->size() == 0 ? $node : null;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'last-child':\n\t\t\t\t$this->elements = $this->map(\n\t\t\t\t\tfunction ($node) {\n\t\t\t\t\t\treturn pq($node)->nextAll()->size() == 0 ? $node : null;\n\t\t\t\t\t}\n\t\t\t\t)->elements;\n\t\t\tbreak;\n\t\t\tcase 'nth-child':\n\t\t\t\t$param = trim($args, \"\\\"'\");\n\t\t\t\tif (! $param)\n\t\t\t\t\tbreak;\n\t\t\t\t\t// nth-child(n+b) to nth-child(1n+b)\n\t\t\t\tif ($param[0] == 'n')\n\t\t\t\t\t$param = '1'.$param;\n\t\t\t\t// :nth-child(index/even/odd/equation)\n\t\t\t\tif ($param == 'even' || $param == 'odd')\n\t\t\t\t\t$mapped = $this->map(\n\t\t\t\t\t\tfunction ($node, $param) {\n\t\t\t\t\t\t\t$index = pq($node)->prevAll()->size()+1;\n\t\t\t\t\t\t\tif ($param == \"even\" && ($index%2) == 0)\n\t\t\t\t\t\t\t\treturn $node;\n\t\t\t\t\t\t\telse if ($param == \"odd\" && $index%2 == 1)\n\t\t\t\t\t\t\t\treturn $node;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnew CallbackParam(), $param\n\t\t\t\t\t);\n\t\t\t\telse if (mb_strlen($param) > 1 && preg_match('/^(\\d*)n([-+]?)(\\d*)/', $param) === 1)\n\t\t\t\t\t// an+b\n\t\t\t\t\t$mapped = $this->map(\n\t\t\t\t\t\tfunction ($node, $param) {\n\t\t\t\t\t\t\t$prevs = pq($node)->prevAll()->size();\n\t\t\t\t\t\t\t$index = 1+$prevs;\n\n\t\t\t\t\t\t\tpreg_match(\"/^(\\d*)n([-+]?)(\\d*)/\", $param, $matches);\n \t\t\t\t\t\t\t$a = intval($matches[1]);\n \t\t\t\t\t\t\t$b = intval($matches[3]);\n \t\t\t\t\t\t\tif( $matches[2] === \"-\" ) {\n \t\t\t\t\t\t\t    $b = -$b;\n \t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ($a > 0) {\n\t\t\t\t\t\t\t\treturn ($index-$b)%$a == 0\n\t\t\t\t\t\t\t\t\t? $node\n\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\t\tphpQuery::debug($a.\"*\".floor($index/$a).\"+$b-1 == \".($a*floor($index/$a)+$b-1).\" ?= $prevs\");\n\t\t\t\t\t\t\t\treturn $a*floor($index/$a)+$b-1 == $prevs\n\t\t\t\t\t\t\t\t\t\t? $node\n\t\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\t} else if ($a == 0)\n\t\t\t\t\t\t\t\treturn $index == $b\n\t\t\t\t\t\t\t\t\t\t? $node\n\t\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t// negative value\n\t\t\t\t\t\t\t\treturn $index <= $b\n\t\t\t\t\t\t\t\t\t\t? $node\n\t\t\t\t\t\t\t\t\t\t: null;\n//\t\t\t\t\t\t\tif (! $b)\n//\t\t\t\t\t\t\t\treturn $index%$a == 0\n//\t\t\t\t\t\t\t\t\t? $node\n//\t\t\t\t\t\t\t\t\t: null;\n//\t\t\t\t\t\t\telse\n//\t\t\t\t\t\t\t\treturn ($index-$b)%$a == 0\n//\t\t\t\t\t\t\t\t\t? $node\n//\t\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnew CallbackParam(), $param\n\t\t\t\t\t);\n\t\t\t\telse\n\t\t\t\t\t// index\n\t\t\t\t\t$mapped = $this->map(\n\t\t\t\t\t\tfunction ($node, $index) {\n\t\t\t\t\t\t\t$prevs = pq($node)->prevAll()->size();\n\t\t\t\t\t\t\tif ($prevs && $prevs == $index-1)\n\t\t\t\t\t\t\t\treturn $node;\n\t\t\t\t\t\t\telse if (! $prevs && $index == 1)\n\t\t\t\t\t\t\t\treturn $node;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnew CallbackParam(), $param\n\t\t\t\t\t);\n\t\t\t\t$this->elements = $mapped->elements;\n\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$this->debug(\"Unknown pseudoclass '{$class}', skipping...\");\n\t\t}\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function __pseudoClassParam($paramsString) {\n\t\t// TODO;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function is($selector, $nodes = null) {\n\t\tphpQuery::debug(array(\"Is:\", $selector));\n\t\tif (! $selector)\n\t\t\treturn false;\n\t\t$oldStack = $this->elements;\n\t\t$returnArray = false;\n\t\tif ($nodes && is_array($nodes)) {\n\t\t\t$this->elements = $nodes;\n\t\t} else if ($nodes)\n\t\t\t$this->elements = array($nodes);\n\t\t$this->filter($selector, true);\n\t\t$stack = $this->elements;\n\t\t$this->elements = $oldStack;\n\t\tif ($nodes)\n\t\t\treturn $stack ? $stack : null;\n\t\treturn (bool)count($stack);\n\t}\n\t/**\n\t * Enter description here...\n\t * jQuery difference.\n\t *\n\t * Callback:\n\t * - $index int\n\t * - $node DOMNode\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @link http://docs.jquery.com/Traversing/filter\n\t */\n\tpublic function filterCallback($callback, $_skipHistory = false) {\n\t\tif (! $_skipHistory) {\n\t\t\t$this->elementsBackup = $this->elements;\n\t\t\t$this->debug(\"Filtering by callback\");\n\t\t}\n\t\t$newStack = array();\n\t\tforeach($this->elements as $index => $node) {\n\t\t\t$result = phpQuery::callbackRun($callback, array($index, $node));\n\t\t\tif (is_null($result) || (! is_null($result) && $result))\n\t\t\t\t$newStack[] = $node;\n\t\t}\n\t\t$this->elements = $newStack;\n\t\treturn $_skipHistory\n\t\t\t? $this\n\t\t\t: $this->newInstance();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @link http://docs.jquery.com/Traversing/filter\n\t */\n\tpublic function filter($selectors, $_skipHistory = false) {\n\t\tif ($selectors instanceof Callback OR $selectors instanceof Closure)\n\t\t\treturn $this->filterCallback($selectors, $_skipHistory);\n\t\tif (! $_skipHistory)\n\t\t\t$this->elementsBackup = $this->elements;\n\t\t$notSimpleSelector = array(' ', '>', '~', '+', '/');\n\t\tif (! is_array($selectors))\n\t\t\t$selectors = $this->parseSelector($selectors);\n\t\tif (! $_skipHistory)\n\t\t\t$this->debug(array(\"Filtering:\", $selectors));\n\t\t$finalStack = array();\n\t\tforeach($selectors as $selector) {\n\t\t\t$stack = array();\n\t\t\tif (! $selector)\n\t\t\t\tbreak;\n\t\t\t// avoid first space or /\n\t\t\tif (in_array($selector[0], $notSimpleSelector))\n\t\t\t\t$selector = array_slice($selector, 1);\n\t\t\t// PER NODE selector chunks\n\t\t\tforeach($this->stack() as $node) {\n\t\t\t\t$break = false;\n\t\t\t\tforeach($selector as $s) {\n\t\t\t\t\tif (!($node instanceof DOMELEMENT)) {\n\t\t\t\t\t\t// all besides DOMElement\n\t\t\t\t\t\tif ( $s[0] == '[') {\n\t\t\t\t\t\t\t$attr = trim($s, '[]');\n\t\t\t\t\t\t\tif ( mb_strpos($attr, '=')) {\n\t\t\t\t\t\t\t\tlist( $attr, $val ) = explode('=', $attr);\n\t\t\t\t\t\t\t\tif ($attr == 'nodeType' && $node->nodeType != $val)\n\t\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// DOMElement only\n\t\t\t\t\t\t// ID\n\t\t\t\t\t\tif ( $s[0] == '#') {\n\t\t\t\t\t\t\tif ( $node->getAttribute('id') != substr($s, 1) )\n\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t// CLASSES\n\t\t\t\t\t\t} else if ( $s[0] == '.') {\n\t\t\t\t\t\t\tif (! $this->matchClasses( $s, $node ) )\n\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t// ATTRS\n\t\t\t\t\t\t} else if ( $s[0] == '[') {\n\t\t\t\t\t\t\t// strip side brackets\n\t\t\t\t\t\t\t$attr = trim($s, '[]');\n\t\t\t\t\t\t\tif (mb_strpos($attr, '=')) {\n\t\t\t\t\t\t\t\tlist($attr, $val) = explode('=', $attr);\n\t\t\t\t\t\t\t\t$val = self::unQuote($val);\n\t\t\t\t\t\t\t\tif ($attr == 'nodeType') {\n\t\t\t\t\t\t\t\t\tif ($val != $node->nodeType)\n\t\t\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t\t} else if ($this->isRegexp($attr)) {\n\t\t\t\t\t\t\t\t\t$val = extension_loaded('mbstring') && phpQuery::$mbstringSupport\n\t\t\t\t\t\t\t\t\t\t? quotemeta(trim($val, '\"\\''))\n\t\t\t\t\t\t\t\t\t\t: preg_quote(trim($val, '\"\\''), '@');\n\t\t\t\t\t\t\t\t\t// switch last character\n\t\t\t\t\t\t\t\t\tswitch( substr($attr, -1)) {\n\t\t\t\t\t\t\t\t\t\t// quotemeta used insted of preg_quote\n\t\t\t\t\t\t\t\t\t\t// http://code.google.com/p/phpquery/issues/detail?id=76\n\t\t\t\t\t\t\t\t\t\tcase '^':\n\t\t\t\t\t\t\t\t\t\t\t$pattern = '^'.$val;\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase '*':\n\t\t\t\t\t\t\t\t\t\t\t$pattern = '.*'.$val.'.*';\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase '$':\n\t\t\t\t\t\t\t\t\t\t\t$pattern = '.*'.$val.'$';\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// cut last character\n\t\t\t\t\t\t\t\t\t$attr = substr($attr, 0, -1);\n\t\t\t\t\t\t\t\t\t$isMatch = extension_loaded('mbstring') && phpQuery::$mbstringSupport\n\t\t\t\t\t\t\t\t\t\t? mb_ereg_match($pattern, $node->getAttribute($attr))\n\t\t\t\t\t\t\t\t\t\t: preg_match(\"@{$pattern}@\", $node->getAttribute($attr));\n\t\t\t\t\t\t\t\t\tif (! $isMatch)\n\t\t\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t\t} else if ($node->getAttribute($attr) != $val)\n\t\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t} else if (! $node->hasAttribute($attr))\n\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t// PSEUDO CLASSES\n\t\t\t\t\t\t} else if ( $s[0] == ':') {\n\t\t\t\t\t\t\t// skip\n\t\t\t\t\t\t// TAG\n\t\t\t\t\t\t} else if (trim($s)) {\n\t\t\t\t\t\t\tif ($s != '*') {\n\t\t\t\t\t\t\t\t// TODO namespaces\n\t\t\t\t\t\t\t\tif (isset($node->tagName)) {\n\t\t\t\t\t\t\t\t\tif ($node->tagName != $s)\n\t\t\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t\t} else if ($s == 'html' && ! $this->isRoot($node))\n\t\t\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t// AVOID NON-SIMPLE SELECTORS\n\t\t\t\t\t\t} else if (in_array($s, $notSimpleSelector)) {\n\t\t\t\t\t\t\t$break = true;\n\t\t\t\t\t\t\t$this->debug(array('Skipping non simple selector', $selector));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ($break)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// if element passed all chunks of selector - add it to new stack\n\t\t\t\tif (! $break )\n\t\t\t\t\t$stack[] = $node;\n\t\t\t}\n\t\t\t$tmpStack = $this->elements;\n\t\t\t$this->elements = $stack;\n\t\t\t// PER ALL NODES selector chunks\n\t\t\tforeach($selector as $s)\n\t\t\t\t// PSEUDO CLASSES\n\t\t\t\tif ($s[0] == ':')\n\t\t\t\t\t$this->pseudoClasses($s);\n\t\t\tforeach($this->elements as $node)\n\t\t\t\t// XXX it should be merged without duplicates\n\t\t\t\t// but jQuery doesnt do that\n\t\t\t\t$finalStack[] = $node;\n\t\t\t$this->elements = $tmpStack;\n\t\t}\n\t\t$this->elements = $finalStack;\n\t\tif ($_skipHistory) {\n\t\t\treturn $this;\n\t\t} else {\n\t\t\t$this->debug(\"Stack length after filter(): \".count($finalStack));\n\t\t\treturn $this->newInstance();\n\t\t}\n\t}\n\t/**\n\t *\n\t * @param $value\n\t * @return unknown_type\n\t * @TODO implement in all methods using passed parameters\n\t */\n\tprotected static function unQuote($value) {\n\t\treturn $value[0] == '\\'' || $value[0] == '\"'\n\t\t\t? substr($value, 1, -1)\n\t\t\t: $value;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @link http://docs.jquery.com/Ajax/load\n\t * @return phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo Support $selector\n\t */\n\tpublic function load($url, $data = null, $callback = null) {\n\t\tif ($data && ! is_array($data)) {\n\t\t\t$callback = $data;\n\t\t\t$data = null;\n\t\t}\n\t\tif (mb_strpos($url, ' ') !== false) {\n\t\t\t$matches = null;\n\t\t\tif (extension_loaded('mbstring') && phpQuery::$mbstringSupport)\n\t\t\t\tmb_ereg('^([^ ]+) (.*)$', $url, $matches);\n\t\t\telse\n\t\t\t\tpreg_match('^([^ ]+) (.*)$', $url, $matches);\n\t\t\t$url = $matches[1];\n\t\t\t$selector = $matches[2];\n\t\t\t// FIXME this sucks, pass as callback param\n\t\t\t$this->_loadSelector = $selector;\n\t\t}\n\t\t$ajax = array(\n\t\t\t'url' => $url,\n\t\t\t'type' => $data ? 'POST' : 'GET',\n\t\t\t'data' => $data,\n\t\t\t'complete' => $callback,\n\t\t\t'success' => array($this, '__loadSuccess')\n\t\t);\n\t\tphpQuery::ajax($ajax);\n\t\treturn $this;\n\t}\n\t/**\n\t * @access private\n\t * @param $html\n\t * @return unknown_type\n\t */\n\tpublic function __loadSuccess($html) {\n\t\tif ($this->_loadSelector) {\n\t\t\t$html = phpQuery::newDocument($html)->find($this->_loadSelector);\n\t\t\tunset($this->_loadSelector);\n\t\t}\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tphpQuery::pq($node, $this->getDocumentID())\n\t\t\t\t->markup($html);\n\t\t}\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo\n\t */\n\tpublic function css() {\n\t\t// TODO\n\t\treturn $this;\n\t}\n\t/**\n\t * @todo\n\t *\n\t */\n\tpublic function show(){\n\t\t// TODO\n\t\treturn $this;\n\t}\n\t/**\n\t * @todo\n\t *\n\t */\n\tpublic function hide(){\n\t\t// TODO\n\t\treturn $this;\n\t}\n\t/**\n\t * Trigger a type of event on every matched element.\n\t *\n\t * @param unknown_type $type\n\t * @param unknown_type $data\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @TODO support more than event in $type (space-separated)\n\t */\n\tpublic function trigger($type, $data = array()) {\n\t\tforeach($this->elements as $node)\n\t\t\tphpQueryEvents::trigger($this->getDocumentID(), $type, $data, $node);\n\t\treturn $this;\n\t}\n\t/**\n\t * This particular method triggers all bound event handlers on an element (for a specific event type) WITHOUT executing the browsers default actions.\n\t *\n\t * @param unknown_type $type\n\t * @param unknown_type $data\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @TODO\n\t */\n\tpublic function triggerHandler($type, $data = array()) {\n\t\t// TODO;\n\t}\n\t/**\n\t * Binds a handler to one or more events (like click) for each matched element.\n\t * Can also bind custom events.\n\t *\n\t * @param unknown_type $type\n\t * @param unknown_type $data Optional\n\t * @param unknown_type $callback\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @TODO support '!' (exclusive) events\n\t * @TODO support more than event in $type (space-separated)\n\t */\n\tpublic function bind($type, $data, $callback = null) {\n\t\t// TODO check if $data is callable, not using is_callable\n\t\tif (! isset($callback)) {\n\t\t\t$callback = $data;\n\t\t\t$data = null;\n\t\t}\n\t\tforeach($this->elements as $node)\n\t\t\tphpQueryEvents::add($this->getDocumentID(), $node, $type, $data, $callback);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param unknown_type $type\n\t * @param unknown_type $callback\n\t * @return unknown\n\t * @TODO namespace events\n\t * @TODO support more than event in $type (space-separated)\n\t */\n\tpublic function unbind($type = null, $callback = null) {\n\t\tforeach($this->elements as $node)\n\t\t\tphpQueryEvents::remove($this->getDocumentID(), $node, $type, $callback);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function change($callback = null) {\n\t\tif ($callback)\n\t\t\treturn $this->bind('change', $callback);\n\t\treturn $this->trigger('change');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function submit($callback = null) {\n\t\tif ($callback)\n\t\t\treturn $this->bind('submit', $callback);\n\t\treturn $this->trigger('submit');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function click($callback = null) {\n\t\tif ($callback)\n\t\t\treturn $this->bind('click', $callback);\n\t\treturn $this->trigger('click');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrapAllOld($wrapper) {\n\t\t$wrapper = pq($wrapper)->_clone();\n\t\tif (! $wrapper->length() || ! $this->length() )\n\t\t\treturn $this;\n\t\t$wrapper->insertBefore($this->elements[0]);\n\t\t$deepest = $wrapper->elements[0];\n\t\twhile($deepest->firstChild && $deepest->firstChild instanceof DOMELEMENT)\n\t\t\t$deepest = $deepest->firstChild;\n\t\tpq($deepest)->append($this);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * TODO testme...\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrapAll($wrapper) {\n\t\tif (! $this->length())\n\t\t\treturn $this;\n\t\treturn phpQuery::pq($wrapper, $this->getDocumentID())\n\t\t\t->clone()\n\t\t\t->insertBefore($this->get(0))\n\t\t\t->map(array($this, '___wrapAllCallback'))\n\t\t\t->append($this);\n\t}\n  /**\n   *\n\t * @param $node\n\t * @return unknown_type\n\t * @access private\n   */\n\tpublic function ___wrapAllCallback($node) {\n\t\t$deepest = $node;\n\t\twhile($deepest->firstChild && $deepest->firstChild instanceof DOMELEMENT)\n\t\t\t$deepest = $deepest->firstChild;\n\t\treturn $deepest;\n\t}\n\t/**\n\t * Enter description here...\n\t * NON JQUERY METHOD\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrapAllPHP($codeBefore, $codeAfter) {\n\t\treturn $this\n\t\t\t->slice(0, 1)\n\t\t\t\t->beforePHP($codeBefore)\n\t\t\t->end()\n\t\t\t->slice(-1)\n\t\t\t\t->afterPHP($codeAfter)\n\t\t\t->end();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrap($wrapper) {\n\t\tforeach($this->stack() as $node)\n\t\t\tphpQuery::pq($node, $this->getDocumentID())->wrapAll($wrapper);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrapPHP($codeBefore, $codeAfter) {\n\t\tforeach($this->stack() as $node)\n\t\t\tphpQuery::pq($node, $this->getDocumentID())->wrapAllPHP($codeBefore, $codeAfter);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrapInner($wrapper) {\n\t\tforeach($this->stack() as $node)\n\t\t\tphpQuery::pq($node, $this->getDocumentID())->contents()->wrapAll($wrapper);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function wrapInnerPHP($codeBefore, $codeAfter) {\n\t\tforeach($this->stack(1) as $node)\n\t\t\tphpQuery::pq($node, $this->getDocumentID())->contents()\n\t\t\t\t->wrapAllPHP($codeBefore, $codeAfter);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @testme Support for text nodes\n\t */\n\tpublic function contents() {\n\t\t$stack = array();\n\t\tforeach($this->stack(1) as $el) {\n\t\t\t// FIXME (fixed) http://code.google.com/p/phpquery/issues/detail?id=56\n//\t\t\tif (! isset($el->childNodes))\n//\t\t\t\tcontinue;\n\t\t\tforeach($el->childNodes as $node) {\n\t\t\t\t$stack[] = $node;\n\t\t\t}\n\t\t}\n\t\treturn $this->newInstance($stack);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * jQuery difference.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function contentsUnwrap() {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tif (! $node->parentNode )\n\t\t\t\tcontinue;\n\t\t\t$childNodes = array();\n\t\t\t// any modification in DOM tree breaks childNodes iteration, so cache them first\n\t\t\tforeach($node->childNodes as $chNode )\n\t\t\t\t$childNodes[] = $chNode;\n\t\t\tforeach($childNodes as $chNode )\n//\t\t\t\t$node->parentNode->appendChild($chNode);\n\t\t\t\t$node->parentNode->insertBefore($chNode, $node);\n\t\t\t$node->parentNode->removeChild($node);\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * jQuery difference.\n\t */\n\tpublic function switchWith($markup) {\n\t\t$markup = pq($markup, $this->getDocumentID());\n\t\t$content = null;\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tpq($node)\n\t\t\t\t->contents()->toReference($content)->end()\n\t\t\t\t->replaceWith($markup->clone()->append($content));\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function eq($num) {\n\t\t$oldStack = $this->elements;\n\t\t$this->elementsBackup = $this->elements;\n\t\t$this->elements = array();\n\t\tif ( isset($oldStack[$num]) )\n\t\t\t$this->elements[] = $oldStack[$num];\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function size() {\n\t\treturn count($this->elements);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @deprecated Use length as attribute\n\t */\n\tpublic function length() {\n\t\treturn $this->size();\n\t}\n\tpublic function count() {\n\t\treturn $this->size();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo $level\n\t */\n\tpublic function end($level = 1) {\n//\t\t$this->elements = array_pop( $this->history );\n//\t\treturn $this;\n//\t\t$this->previous->DOM = $this->DOM;\n//\t\t$this->previous->XPath = $this->XPath;\n\t\treturn $this->previous\n\t\t\t? $this->previous\n\t\t\t: $this;\n\t}\n\t/**\n\t * Enter description here...\n\t * Normal use ->clone() .\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @access private\n\t */\n\tpublic function _clone() {\n\t\t$newStack = array();\n\t\t//pr(array('copy... ', $this->whois()));\n\t\t//$this->dumpHistory('copy');\n\t\t$this->elementsBackup = $this->elements;\n\t\tforeach($this->elements as $node) {\n\t\t\t$newStack[] = $node->cloneNode(true);\n\t\t}\n\t\t$this->elements = $newStack;\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function replaceWithPHP($code) {\n\t\treturn $this->replaceWith(phpQuery::php($code));\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery $content\n\t * @link http://docs.jquery.com/Manipulation/replaceWith#content\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function replaceWith($content) {\n\t\treturn $this->after($content)->remove();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String $selector\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo this works ?\n\t */\n\tpublic function replaceAll($selector) {\n\t\tforeach(phpQuery::pq($selector, $this->getDocumentID()) as $node)\n\t\t\tphpQuery::pq($node, $this->getDocumentID())\n\t\t\t\t->after($this->_clone())\n\t\t\t\t->remove();\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function remove($selector = null) {\n\t\t$loop = $selector\n\t\t\t? $this->filter($selector)->elements\n\t\t\t: $this->elements;\n\t\tforeach($loop as $node) {\n\t\t\tif (! $node->parentNode )\n\t\t\t\tcontinue;\n\t\t\tif (isset($node->tagName))\n\t\t\t\t$this->debug(\"Removing '{$node->tagName}'\");\n\t\t\t$node->parentNode->removeChild($node);\n\t\t\t// Mutation event\n\t\t\t$event = new DOMEvent(array(\n\t\t\t\t'target' => $node,\n\t\t\t\t'type' => 'DOMNodeRemoved'\n\t\t\t));\n\t\t\tphpQueryEvents::trigger($this->getDocumentID(),\n\t\t\t\t$event->type, array($event), $node\n\t\t\t);\n\t\t}\n\t\treturn $this;\n\t}\n\tprotected function markupEvents($newMarkup, $oldMarkup, $node) {\n\t\tif ($node->tagName == 'textarea' && $newMarkup != $oldMarkup) {\n\t\t\t$event = new DOMEvent(array(\n\t\t\t\t'target' => $node,\n\t\t\t\t'type' => 'change'\n\t\t\t));\n\t\t\tphpQueryEvents::trigger($this->getDocumentID(),\n\t\t\t\t$event->type, array($event), $node\n\t\t\t);\n\t\t}\n\t}\n\t/**\n\t * jQuey difference\n\t *\n\t * @param $markup\n\t * @return unknown_type\n\t * @TODO trigger change event for textarea\n\t */\n\tpublic function markup($markup = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n\t\t$args = func_get_args();\n\t\tif ($this->documentWrapper->isXML)\n\t\t\treturn call_user_func_array(array($this, 'xml'), $args);\n\t\telse\n\t\t\treturn call_user_func_array(array($this, 'html'), $args);\n\t}\n\t/**\n\t * jQuey difference\n\t *\n\t * @param $markup\n\t * @return unknown_type\n\t */\n\tpublic function markupOuter($callback1 = null, $callback2 = null, $callback3 = null) {\n\t\t$args = func_get_args();\n\t\tif ($this->documentWrapper->isXML)\n\t\t\treturn call_user_func_array(array($this, 'xmlOuter'), $args);\n\t\telse\n\t\t\treturn call_user_func_array(array($this, 'htmlOuter'), $args);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param unknown_type $html\n\t * @return string|phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @TODO force html result\n\t */\n\tpublic function html($html = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n\t\tif (isset($html)) {\n\t\t\t// INSERT\n\t\t\t$nodes = $this->documentWrapper->import($html);\n\t\t\t$this->empty();\n\t\t\tforeach($this->stack(1) as $alreadyAdded => $node) {\n\t\t\t\t// for now, limit events for textarea\n\t\t\t\tif (($this->isXHTML() || $this->isHTML()) && $node->tagName == 'textarea')\n\t\t\t\t\t$oldHtml = pq($node, $this->getDocumentID())->markup();\n\t\t\t\tforeach($nodes as $newNode) {\n\t\t\t\t\t$node->appendChild($alreadyAdded\n\t\t\t\t\t\t? $newNode->cloneNode(true)\n\t\t\t\t\t\t: $newNode\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// for now, limit events for textarea\n\t\t\t\tif (($this->isXHTML() || $this->isHTML()) && $node->tagName == 'textarea')\n\t\t\t\t\t$this->markupEvents($html, $oldHtml, $node);\n\t\t\t}\n\t\t\treturn $this;\n\t\t} else {\n\t\t\t// FETCH\n\t\t\t$return = $this->documentWrapper->markup($this->elements, true);\n\t\t\t$args = func_get_args();\n\t\t\tforeach(array_slice($args, 1) as $callback) {\n\t\t\t\t$return = phpQuery::callbackRun($callback, array($return));\n\t\t\t}\n\t\t\treturn $return;\n\t\t}\n\t}\n\t/**\n\t * @TODO force xml result\n\t */\n\tpublic function xml($xml = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n\t\t$args = func_get_args();\n\t\treturn call_user_func_array(array($this, 'html'), $args);\n\t}\n\t/**\n\t * Enter description here...\n\t * @TODO force html result\n\t *\n\t * @return String\n\t */\n\tpublic function htmlOuter($callback1 = null, $callback2 = null, $callback3 = null) {\n\t\t$markup = $this->documentWrapper->markup($this->elements);\n\t\t// pass thou callbacks\n\t\t$args = func_get_args();\n\t\tforeach($args as $callback) {\n\t\t\t$markup = phpQuery::callbackRun($callback, array($markup));\n\t\t}\n\t\treturn $markup;\n\t}\n\t/**\n\t * @TODO force xml result\n\t */\n\tpublic function xmlOuter($callback1 = null, $callback2 = null, $callback3 = null) {\n\t\t$args = func_get_args();\n\t\treturn call_user_func_array(array($this, 'htmlOuter'), $args);\n\t}\n\tpublic function __toString() {\n\t\treturn $this->markupOuter();\n\t}\n\t/**\n\t * Just like html(), but returns markup with VALID (dangerous) PHP tags.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo support returning markup with PHP tags when called without param\n\t */\n\tpublic function php($code = null) {\n\t\treturn $this->markupPHP($code);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param $code\n\t * @return unknown_type\n\t */\n\tpublic function markupPHP($code = null) {\n\t\treturn isset($code)\n\t\t\t? $this->markup(phpQuery::php($code))\n\t\t\t: phpQuery::markupToPHP($this->markup());\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param $code\n\t * @return unknown_type\n\t */\n\tpublic function markupOuterPHP() {\n\t\treturn phpQuery::markupToPHP($this->markupOuter());\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function children($selector = null) {\n\t\t$stack = array();\n\t\tforeach($this->stack(1) as $node) {\n//\t\t\tforeach($node->getElementsByTagName('*') as $newNode) {\n\t\t\tforeach($node->childNodes as $newNode) {\n\t\t\t\tif ($newNode->nodeType != 1)\n\t\t\t\t\tcontinue;\n\t\t\t\tif ($selector && ! $this->is($selector, $newNode))\n\t\t\t\t\tcontinue;\n\t\t\t\tif ($this->elementsContainsNode($newNode, $stack))\n\t\t\t\t\tcontinue;\n\t\t\t\t$stack[] = $newNode;\n\t\t\t}\n\t\t}\n\t\t$this->elementsBackup = $this->elements;\n\t\t$this->elements = $stack;\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function ancestors($selector = null) {\n\t\treturn $this->children( $selector );\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function append( $content) {\n\t\treturn $this->insert($content, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function appendPHP( $content) {\n\t\treturn $this->insert(\"<php><!-- {$content} --></php>\", 'append');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function appendTo( $seletor) {\n\t\treturn $this->insert($seletor, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function prepend( $content) {\n\t\treturn $this->insert($content, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @todo accept many arguments, which are joined, arrays maybe also\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function prependPHP( $content) {\n\t\treturn $this->insert(\"<php><!-- {$content} --></php>\", 'prepend');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function prependTo( $seletor) {\n\t\treturn $this->insert($seletor, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function before($content) {\n\t\treturn $this->insert($content, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function beforePHP( $content) {\n\t\treturn $this->insert(\"<php><!-- {$content} --></php>\", 'before');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param String|phpQuery\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function insertBefore( $seletor) {\n\t\treturn $this->insert($seletor, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function after( $content) {\n\t\treturn $this->insert($content, __FUNCTION__);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function afterPHP( $content) {\n\t\treturn $this->insert(\"<php><!-- {$content} --></php>\", 'after');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function insertAfter( $seletor) {\n\t\treturn $this->insert($seletor, __FUNCTION__);\n\t}\n\t/**\n\t * Internal insert method. Don't use it.\n\t *\n\t * @param unknown_type $target\n\t * @param unknown_type $type\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @access private\n\t */\n\tpublic function insert($target, $type) {\n\t\t$this->debug(\"Inserting data with '{$type}'\");\n\t\t$to = false;\n\t\tswitch( $type) {\n\t\t\tcase 'appendTo':\n\t\t\tcase 'prependTo':\n\t\t\tcase 'insertBefore':\n\t\t\tcase 'insertAfter':\n\t\t\t\t$to = true;\n\t\t}\n\t\tswitch(gettype($target)) {\n\t\t\tcase 'string':\n\t\t\t\t$insertFrom = $insertTo = array();\n\t\t\t\tif ($to) {\n\t\t\t\t\t// INSERT TO\n\t\t\t\t\t$insertFrom = $this->elements;\n\t\t\t\t\tif (phpQuery::isMarkup($target)) {\n\t\t\t\t\t\t// $target is new markup, import it\n\t\t\t\t\t\t$insertTo = $this->documentWrapper->import($target);\n\t\t\t\t\t// insert into selected element\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// $tagret is a selector\n\t\t\t\t\t\t$thisStack = $this->elements;\n\t\t\t\t\t\t$this->toRoot();\n\t\t\t\t\t\t$insertTo = $this->find($target)->elements;\n\t\t\t\t\t\t$this->elements = $thisStack;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// INSERT FROM\n\t\t\t\t\t$insertTo = $this->elements;\n\t\t\t\t\t$insertFrom = $this->documentWrapper->import($target);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'object':\n\t\t\t\t$insertFrom = $insertTo = array();\n\t\t\t\t// phpQuery\n\t\t\t\tif ($target instanceof self) {\n\t\t\t\t\tif ($to) {\n\t\t\t\t\t\t$insertTo = $target->elements;\n\t\t\t\t\t\tif ($this->documentFragment && $this->stackIsRoot())\n\t\t\t\t\t\t\t// get all body children\n//\t\t\t\t\t\t\t$loop = $this->find('body > *')->elements;\n\t\t\t\t\t\t\t// TODO test it, test it hard...\n//\t\t\t\t\t\t\t$loop = $this->newInstance($this->root)->find('> *')->elements;\n\t\t\t\t\t\t\t$loop = $this->root->childNodes;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$loop = $this->elements;\n\t\t\t\t\t\t// import nodes if needed\n\t\t\t\t\t\t$insertFrom = $this->getDocumentID() == $target->getDocumentID()\n\t\t\t\t\t\t\t? $loop\n\t\t\t\t\t\t\t: $target->documentWrapper->import($loop);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$insertTo = $this->elements;\n\t\t\t\t\t\tif ( $target->documentFragment && $target->stackIsRoot() )\n\t\t\t\t\t\t\t// get all body children\n//\t\t\t\t\t\t\t$loop = $target->find('body > *')->elements;\n\t\t\t\t\t\t\t$loop = $target->root->childNodes;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$loop = $target->elements;\n\t\t\t\t\t\t// import nodes if needed\n\t\t\t\t\t\t$insertFrom = $this->getDocumentID() == $target->getDocumentID()\n\t\t\t\t\t\t\t? $loop\n\t\t\t\t\t\t\t: $this->documentWrapper->import($loop);\n\t\t\t\t\t}\n\t\t\t\t// DOMNODE\n\t\t\t\t} elseif ($target instanceof DOMNODE) {\n\t\t\t\t\t// import node if needed\n//\t\t\t\t\tif ( $target->ownerDocument != $this->DOM )\n//\t\t\t\t\t\t$target = $this->DOM->importNode($target, true);\n\t\t\t\t\tif ( $to) {\n\t\t\t\t\t\t$insertTo = array($target);\n\t\t\t\t\t\tif ($this->documentFragment && $this->stackIsRoot())\n\t\t\t\t\t\t\t// get all body children\n\t\t\t\t\t\t\t$loop = $this->root->childNodes;\n//\t\t\t\t\t\t\t$loop = $this->find('body > *')->elements;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$loop = $this->elements;\n\t\t\t\t\t\tforeach($loop as $fromNode)\n\t\t\t\t\t\t\t// import nodes if needed\n\t\t\t\t\t\t\t$insertFrom[] = ! $fromNode->ownerDocument->isSameNode($target->ownerDocument)\n\t\t\t\t\t\t\t\t? $target->ownerDocument->importNode($fromNode, true)\n\t\t\t\t\t\t\t\t: $fromNode;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// import node if needed\n\t\t\t\t\t\tif (! $target->ownerDocument->isSameNode($this->document))\n\t\t\t\t\t\t\t$target = $this->document->importNode($target, true);\n\t\t\t\t\t\t$insertTo = $this->elements;\n\t\t\t\t\t\t$insertFrom[] = $target;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\tphpQuery::debug(\"From \".count($insertFrom).\"; To \".count($insertTo).\" nodes\");\n\t\tforeach($insertTo as $insertNumber => $toNode) {\n\t\t\t// we need static relative elements in some cases\n\t\t\tswitch( $type) {\n\t\t\t\tcase 'prependTo':\n\t\t\t\tcase 'prepend':\n\t\t\t\t\t$firstChild = $toNode->firstChild;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'insertAfter':\n\t\t\t\tcase 'after':\n\t\t\t\t\t$nextSibling = $toNode->nextSibling;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tforeach($insertFrom as $fromNode) {\n\t\t\t\t// clone if inserted already before\n\t\t\t\t$insert = $insertNumber\n\t\t\t\t\t? $fromNode->cloneNode(true)\n\t\t\t\t\t: $fromNode;\n\t\t\t\tswitch($type) {\n\t\t\t\t\tcase 'appendTo':\n\t\t\t\t\tcase 'append':\n//\t\t\t\t\t\t$toNode->insertBefore(\n//\t\t\t\t\t\t\t$fromNode,\n//\t\t\t\t\t\t\t$toNode->lastChild->nextSibling\n//\t\t\t\t\t\t);\n\t\t\t\t\t\t$toNode->appendChild($insert);\n\t\t\t\t\t\t$eventTarget = $insert;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'prependTo':\n\t\t\t\t\tcase 'prepend':\n\t\t\t\t\t\t$toNode->insertBefore(\n\t\t\t\t\t\t\t$insert,\n\t\t\t\t\t\t\t$firstChild\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'insertBefore':\n\t\t\t\t\tcase 'before':\n\t\t\t\t\t\tif (! $toNode->parentNode)\n\t\t\t\t\t\t\tthrow new Exception(\"No parentNode, can't do {$type}()\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$toNode->parentNode->insertBefore(\n\t\t\t\t\t\t\t\t$insert,\n\t\t\t\t\t\t\t\t$toNode\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'insertAfter':\n\t\t\t\t\tcase 'after':\n\t\t\t\t\t\tif (! $toNode->parentNode)\n\t\t\t\t\t\t\tthrow new Exception(\"No parentNode, can't do {$type}()\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$toNode->parentNode->insertBefore(\n\t\t\t\t\t\t\t\t$insert,\n\t\t\t\t\t\t\t\t$nextSibling\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Mutation event\n\t\t\t\t$event = new DOMEvent(array(\n\t\t\t\t\t'target' => $insert,\n\t\t\t\t\t'type' => 'DOMNodeInserted'\n\t\t\t\t));\n\t\t\t\tphpQueryEvents::trigger($this->getDocumentID(),\n\t\t\t\t\t$event->type, array($event), $insert\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return Int\n\t */\n\tpublic function index($subject) {\n\t\t$index = -1;\n\t\t$subject = $subject instanceof phpQueryObject\n\t\t\t? $subject->elements[0]\n\t\t\t: $subject;\n\t\tforeach($this->newInstance() as $k => $node) {\n\t\t\tif ($node->isSameNode($subject))\n\t\t\t\t$index = $k;\n\t\t}\n\t\treturn $index;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param unknown_type $start\n\t * @param unknown_type $end\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @testme\n\t */\n\tpublic function slice($start, $end = null) {\n//\t\t$last = count($this->elements)-1;\n//\t\t$end = $end\n//\t\t\t? min($end, $last)\n//\t\t\t: $last;\n//\t\tif ($start < 0)\n//\t\t\t$start = $last+$start;\n//\t\tif ($start > $last)\n//\t\t\treturn array();\n\t\tif ($end > 0)\n\t\t\t$end = $end-$start;\n\t\treturn $this->newInstance(\n\t\t\tarray_slice($this->elements, $start, $end)\n\t\t);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function reverse() {\n\t\t$this->elementsBackup = $this->elements;\n\t\t$this->elements = array_reverse($this->elements);\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * Return joined text content.\n\t * @return String\n\t */\n\tpublic function text($text = null, $callback1 = null, $callback2 = null, $callback3 = null) {\n\t\tif (isset($text))\n\t\t\treturn $this->html(htmlspecialchars($text));\n\t\t$args = func_get_args();\n\t\t$args = array_slice($args, 1);\n\t\t$return = '';\n\t\tforeach($this->elements as $node) {\n\t\t\t$text = $node->textContent;\n\t\t\tif (count($this->elements) > 1 && $text)\n\t\t\t\t$text .= \"\\n\";\n\t\t\tforeach($args as $callback) {\n\t\t\t\t$text = phpQuery::callbackRun($callback, array($text));\n\t\t\t}\n\t\t\t$return .= $text;\n\t\t}\n\t\treturn $return;\n\t}\n    /**\n     * @return The text content of each matching element, like\n     * text() but returns an array with one entry per matched element.\n     * Read only.\n     */\n    public function texts($attr = null) {\n        $results = array();\n        foreach($this->elements as $node) {\n            $results[] = $node->textContent;\n        }\n        return $results;\n    }\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function plugin($class, $file = null) {\n\t\tphpQuery::plugin($class, $file);\n\t\treturn $this;\n\t}\n\t/**\n\t * Deprecated, use $pq->plugin() instead.\n\t *\n\t * @deprecated\n\t * @param $class\n\t * @param $file\n\t * @return unknown_type\n\t */\n\tpublic static function extend($class, $file = null) {\n\t\treturn $this->plugin($class, $file);\n\t}\n\t/**\n\t *\n\t * @access private\n\t * @param $method\n\t * @param $args\n\t * @return unknown_type\n\t */\n\tpublic function __call($method, $args) {\n\t\t$aliasMethods = array('clone', 'empty');\n\t\tif (isset(phpQuery::$extendMethods[$method])) {\n\t\t\tarray_unshift($args, $this);\n\t\t\treturn phpQuery::callbackRun(\n\t\t\t\tphpQuery::$extendMethods[$method], $args\n\t\t\t);\n\t\t} else if (isset(phpQuery::$pluginsMethods[$method])) {\n\t\t\tarray_unshift($args, $this);\n\t\t\t$class = phpQuery::$pluginsMethods[$method];\n\t\t\t$realClass = \"phpQueryObjectPlugin_$class\";\n\t\t\t$return = call_user_func_array(\n\t\t\t\tarray($realClass, $method),\n\t\t\t\t$args\n\t\t\t);\n\t\t\t// XXX deprecate ?\n\t\t\treturn is_null($return)\n\t\t\t\t? $this\n\t\t\t\t: $return;\n\t\t} else if (in_array($method, $aliasMethods)) {\n\t\t\treturn call_user_func_array(array($this, '_'.$method), $args);\n\t\t} else\n\t\t\tthrow new Exception(\"Method '{$method}' doesnt exist\");\n\t}\n\t/**\n\t * Safe rename of next().\n\t *\n\t * Use it ONLY when need to call next() on an iterated object (in same time).\n\t * Normaly there is no need to do such thing ;)\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @access private\n\t */\n\tpublic function _next($selector = null) {\n\t\treturn $this->newInstance(\n\t\t\t$this->getElementSiblings('nextSibling', $selector, true)\n\t\t);\n\t}\n\t/**\n\t * Use prev() and next().\n\t *\n\t * @deprecated\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @access private\n\t */\n\tpublic function _prev($selector = null) {\n\t\treturn $this->prev($selector);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function prev($selector = null) {\n\t\treturn $this->newInstance(\n\t\t\t$this->getElementSiblings('previousSibling', $selector, true)\n\t\t);\n\t}\n\t/**\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo\n\t */\n\tpublic function prevAll($selector = null) {\n\t\treturn $this->newInstance(\n\t\t\t$this->getElementSiblings('previousSibling', $selector)\n\t\t);\n\t}\n\t/**\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo FIXME: returns source elements insted of next siblings\n\t */\n\tpublic function nextAll($selector = null) {\n\t\treturn $this->newInstance(\n\t\t\t$this->getElementSiblings('nextSibling', $selector)\n\t\t);\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function getElementSiblings($direction, $selector = null, $limitToOne = false) {\n\t\t$stack = array();\n\t\t$count = 0;\n\t\tforeach($this->stack() as $node) {\n\t\t\t$test = $node;\n\t\t\twhile( isset($test->{$direction}) && $test->{$direction}) {\n\t\t\t\t$test = $test->{$direction};\n\t\t\t\tif (! $test instanceof DOMELEMENT)\n\t\t\t\t\tcontinue;\n\t\t\t\t$stack[] = $test;\n\t\t\t\tif ($limitToOne)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif ($selector) {\n\t\t\t$stackOld = $this->elements;\n\t\t\t$this->elements = $stack;\n\t\t\t$stack = $this->filter($selector, true)->stack();\n\t\t\t$this->elements = $stackOld;\n\t\t}\n\t\treturn $stack;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function siblings($selector = null) {\n\t\t$stack = array();\n\t\t$siblings = array_merge(\n\t\t\t$this->getElementSiblings('previousSibling', $selector),\n\t\t\t$this->getElementSiblings('nextSibling', $selector)\n\t\t);\n\t\tforeach($siblings as $node) {\n\t\t\tif (! $this->elementsContainsNode($node, $stack))\n\t\t\t\t$stack[] = $node;\n\t\t}\n\t\treturn $this->newInstance($stack);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function not($selector = null) {\n\t\tif (is_string($selector))\n\t\t\tphpQuery::debug(array('not', $selector));\n\t\telse\n\t\t\tphpQuery::debug('not');\n\t\t$stack = array();\n\t\tif ($selector instanceof self || $selector instanceof DOMNODE) {\n\t\t\tforeach($this->stack() as $node) {\n\t\t\t\tif ($selector instanceof self) {\n\t\t\t\t\t$matchFound = false;\n\t\t\t\t\tforeach($selector->stack() as $notNode) {\n\t\t\t\t\t\tif ($notNode->isSameNode($node))\n\t\t\t\t\t\t\t$matchFound = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (! $matchFound)\n\t\t\t\t\t\t$stack[] = $node;\n\t\t\t\t} else if ($selector instanceof DOMNODE) {\n\t\t\t\t\tif (! $selector->isSameNode($node))\n\t\t\t\t\t\t$stack[] = $node;\n\t\t\t\t} else {\n\t\t\t\t\tif (! $this->is($selector))\n\t\t\t\t\t\t$stack[] = $node;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t$orgStack = $this->stack();\n\t\t\t$matched = $this->filter($selector, true)->stack();\n//\t\t\t$matched = array();\n//\t\t\t// simulate OR in filter() instead of AND 5y\n//\t\t\tforeach($this->parseSelector($selector) as $s) {\n//\t\t\t\t$matched = array_merge($matched,\n//\t\t\t\t\t$this->filter(array($s))->stack()\n//\t\t\t\t);\n//\t\t\t}\n\t\t\tforeach($orgStack as $node)\n\t\t\t\tif (! $this->elementsContainsNode($node, $matched))\n\t\t\t\t\t$stack[] = $node;\n\t\t}\n\t\treturn $this->newInstance($stack);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param string|phpQueryObject\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function add($selector = null) {\n\t\tif (! $selector)\n\t\t\treturn $this;\n\t\t$stack = array();\n\t\t$this->elementsBackup = $this->elements;\n\t\t$found = phpQuery::pq($selector, $this->getDocumentID());\n\t\t$this->merge($found->elements);\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * @access private\n\t */\n\tprotected function merge() {\n\t\tforeach(func_get_args() as $nodes)\n\t\t\tforeach($nodes as $newNode )\n\t\t\t\tif (! $this->elementsContainsNode($newNode) )\n\t\t\t\t\t$this->elements[] = $newNode;\n\t}\n\t/**\n\t * @access private\n\t * TODO refactor to stackContainsNode\n\t */\n\tprotected function elementsContainsNode($nodeToCheck, $elementsStack = null) {\n\t\t$loop = ! is_null($elementsStack)\n\t\t\t? $elementsStack\n\t\t\t: $this->elements;\n\t\tforeach($loop as $node) {\n\t\t\tif ( $node->isSameNode( $nodeToCheck ) )\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function parent($selector = null) {\n\t\t$stack = array();\n\t\tforeach($this->elements as $node )\n\t\t\tif ( $node->parentNode && ! $this->elementsContainsNode($node->parentNode, $stack) )\n\t\t\t\t$stack[] = $node->parentNode;\n\t\t$this->elementsBackup = $this->elements;\n\t\t$this->elements = $stack;\n\t\tif ( $selector )\n\t\t\t$this->filter($selector, true);\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function parents($selector = null) {\n\t\t$stack = array();\n\t\tif (! $this->elements )\n\t\t\t$this->debug('parents() - stack empty');\n\t\tforeach($this->elements as $node) {\n\t\t\t$test = $node;\n\t\t\twhile( $test->parentNode) {\n\t\t\t\t$test = $test->parentNode;\n\t\t\t\tif ($this->isRoot($test))\n\t\t\t\t\tbreak;\n\t\t\t\tif (! $this->elementsContainsNode($test, $stack)) {\n\t\t\t\t\t$stack[] = $test;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t$this->elementsBackup = $this->elements;\n\t\t$this->elements = $stack;\n\t\tif ( $selector )\n\t\t\t$this->filter($selector, true);\n\t\treturn $this->newInstance();\n\t}\n\t/**\n\t * Internal stack iterator.\n\t *\n\t * @access private\n\t */\n\tpublic function stack($nodeTypes = null) {\n\t\tif (!isset($nodeTypes))\n\t\t\treturn $this->elements;\n\t\tif (!is_array($nodeTypes))\n\t\t\t$nodeTypes = array($nodeTypes);\n\t\t$return = array();\n\t\tforeach($this->elements as $node) {\n\t\t\tif (in_array($node->nodeType, $nodeTypes))\n\t\t\t\t$return[] = $node;\n\t\t}\n\t\treturn $return;\n\t}\n\t// TODO phpdoc; $oldAttr is result of hasAttribute, before any changes\n\tprotected function attrEvents($attr, $oldAttr, $oldValue, $node) {\n\t\t// skip events for XML documents\n\t\tif (! $this->isXHTML() && ! $this->isHTML())\n\t\t\treturn;\n\t\t$event = null;\n\t\t// identify\n\t\t$isInputValue = $node->tagName == 'input'\n\t\t\t&& (\n\t\t\t\tin_array($node->getAttribute('type'),\n\t\t\t\t\tarray('text', 'password', 'hidden'))\n\t\t\t\t|| !$node->getAttribute('type')\n\t\t\t\t );\n\t\t$isRadio = $node->tagName == 'input'\n\t\t\t&& $node->getAttribute('type') == 'radio';\n\t\t$isCheckbox = $node->tagName == 'input'\n\t\t\t&& $node->getAttribute('type') == 'checkbox';\n\t\t$isOption = $node->tagName == 'option';\n\t\tif ($isInputValue && $attr == 'value' && $oldValue != $node->getAttribute($attr)) {\n\t\t\t$event = new DOMEvent(array(\n\t\t\t\t'target' => $node,\n\t\t\t\t'type' => 'change'\n\t\t\t));\n\t\t} else if (($isRadio || $isCheckbox) && $attr == 'checked' && (\n\t\t\t\t// check\n\t\t\t\t(! $oldAttr && $node->hasAttribute($attr))\n\t\t\t\t// un-check\n\t\t\t\t|| (! $node->hasAttribute($attr) && $oldAttr)\n\t\t\t)) {\n\t\t\t$event = new DOMEvent(array(\n\t\t\t\t'target' => $node,\n\t\t\t\t'type' => 'change'\n\t\t\t));\n\t\t} else if ($isOption && $node->parentNode && $attr == 'selected' && (\n\t\t\t\t// select\n\t\t\t\t(! $oldAttr && $node->hasAttribute($attr))\n\t\t\t\t// un-select\n\t\t\t\t|| (! $node->hasAttribute($attr) && $oldAttr)\n\t\t\t)) {\n\t\t\t$event = new DOMEvent(array(\n\t\t\t\t'target' => $node->parentNode,\n\t\t\t\t'type' => 'change'\n\t\t\t));\n\t\t}\n\t\tif ($event) {\n\t\t\tphpQueryEvents::trigger($this->getDocumentID(),\n\t\t\t\t$event->type, array($event), $node\n\t\t\t);\n\t\t}\n\t}\n\tpublic function attr($attr = null, $value = null) {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tif (! is_null($value)) {\n\t\t\t\t$loop = $attr == '*'\n\t\t\t\t\t? $this->getNodeAttrs($node)\n\t\t\t\t\t: array($attr);\n\t\t\t\tforeach($loop as $a) {\n\t\t\t\t\t$oldValue = $node->getAttribute($a);\n\t\t\t\t\t$oldAttr = $node->hasAttribute($a);\n\t\t\t\t\t// TODO raises an error when charset other than UTF-8\n\t\t\t\t\t// while document's charset is also not UTF-8\n\t\t\t\t\t@$node->setAttribute($a, $value);\n\t\t\t\t\t$this->attrEvents($a, $oldAttr, $oldValue, $node);\n\t\t\t\t}\n\t\t\t} else if ($attr == '*') {\n\t\t\t\t// jQuery difference\n\t\t\t\t$return = array();\n\t\t\t\tforeach($node->attributes as $n => $v)\n\t\t\t\t\t$return[$n] = $v->value;\n\t\t\t\treturn $return;\n\t\t\t} else\n\t\t\t\treturn $node->hasAttribute($attr)\n\t\t\t\t\t? $node->getAttribute($attr)\n\t\t\t\t\t: null;\n\t\t}\n\t\treturn is_null($value)\n\t\t\t? '' : $this;\n\t}\n    /**\n     * @return The same attribute of each matching element, like\n     * attr() but returns an array with one entry per matched element.\n     * Read only.\n     */\n    public function attrs($attr = null) {\n        $results = array();\n        foreach($this->stack(1) as $node) {\n            $results[] = $node->hasAttribute($attr)\n                ? $node->getAttribute($attr)\n                : null;\n        }\n        return $results;\n    }\n\t/**\n\t * @access private\n\t */\n\tprotected function getNodeAttrs($node) {\n\t\t$return = array();\n\t\tforeach($node->attributes as $n => $o)\n\t\t\t$return[] = $n;\n\t\treturn $return;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo check CDATA ???\n\t */\n\tpublic function attrPHP($attr, $code) {\n\t\tif (! is_null($code)) {\n\t\t\t$value = '<'.'?php '.$code.' ?'.'>';\n\t\t\t// TODO tempolary solution\n\t\t\t// http://code.google.com/p/phpquery/issues/detail?id=17\n//\t\t\tif (function_exists('mb_detect_encoding') && mb_detect_encoding($value) == 'ASCII')\n//\t\t\t\t$value\t= mb_convert_encoding($value, 'UTF-8', 'HTML-ENTITIES');\n\t\t}\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tif (! is_null($code)) {\n//\t\t\t\t$attrNode = $this->DOM->createAttribute($attr);\n\t\t\t\t$node->setAttribute($attr, $value);\n//\t\t\t\t$attrNode->value = $value;\n//\t\t\t\t$node->appendChild($attrNode);\n\t\t\t} else if ( $attr == '*') {\n\t\t\t\t// jQuery diff\n\t\t\t\t$return = array();\n\t\t\t\tforeach($node->attributes as $n => $v)\n\t\t\t\t\t$return[$n] = $v->value;\n\t\t\t\treturn $return;\n\t\t\t} else\n\t\t\t\treturn $node->getAttribute($attr);\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function removeAttr($attr) {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\t$loop = $attr == '*'\n\t\t\t\t? $this->getNodeAttrs($node)\n\t\t\t\t: array($attr);\n\t\t\tforeach($loop as $a) {\n\t\t\t\t$oldValue = $node->getAttribute($a);\n\t\t\t\t$node->removeAttribute($a);\n\t\t\t\t$this->attrEvents($a, $oldValue, null, $node);\n\t\t\t}\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Return form element value.\n\t *\n\t * @return String Fields value.\n\t */\n\tpublic function val($val = null) {\n\t\tif (! isset($val)) {\n\t\t\tif ($this->eq(0)->is('select')) {\n\t\t\t\t\t$selected = $this->eq(0)->find('option[selected=selected]');\n\t\t\t\t\tif ($selected->is('[value]'))\n\t\t\t\t\t\treturn $selected->attr('value');\n\t\t\t\t\telse\n\t\t\t\t\t\treturn $selected->text();\n\t\t\t} else if ($this->eq(0)->is('textarea'))\n\t\t\t\t\treturn $this->eq(0)->markup();\n\t\t\t\telse\n\t\t\t\t\treturn $this->eq(0)->attr('value');\n\t\t} else {\n\t\t\t$_val = null;\n\t\t\tforeach($this->stack(1) as $node) {\n\t\t\t\t$node = pq($node, $this->getDocumentID());\n\t\t\t\tif (is_array($val) && in_array($node->attr('type'), array('checkbox', 'radio'))) {\n\t\t\t\t\t$isChecked = in_array($node->attr('value'), $val)\n\t\t\t\t\t\t\t|| in_array($node->attr('name'), $val);\n\t\t\t\t\tif ($isChecked)\n\t\t\t\t\t\t$node->attr('checked', 'checked');\n\t\t\t\t\telse\n\t\t\t\t\t\t$node->removeAttr('checked');\n\t\t\t\t} else if ($node->get(0)->tagName == 'select') {\n\t\t\t\t\tif (! isset($_val)) {\n\t\t\t\t\t\t$_val = array();\n\t\t\t\t\t\tif (! is_array($val))\n\t\t\t\t\t\t\t$_val = array((string)$val);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tforeach($val as $v)\n\t\t\t\t\t\t\t\t$_val[] = $v;\n\t\t\t\t\t}\n\t\t\t\t\tforeach($node['option']->stack(1) as $option) {\n\t\t\t\t\t\t$option = pq($option, $this->getDocumentID());\n\t\t\t\t\t\t$selected = false;\n\t\t\t\t\t\t// XXX: workaround for string comparsion, see issue #96\n\t\t\t\t\t\t// http://code.google.com/p/phpquery/issues/detail?id=96\n\t\t\t\t\t\t$selected = is_null($option->attr('value'))\n\t\t\t\t\t\t\t? in_array($option->markup(), $_val)\n\t\t\t\t\t\t\t: in_array($option->attr('value'), $_val);\n//\t\t\t\t\t\t$optionValue = $option->attr('value');\n//\t\t\t\t\t\t$optionText = $option->text();\n//\t\t\t\t\t\t$optionTextLenght = mb_strlen($optionText);\n//\t\t\t\t\t\tforeach($_val as $v)\n//\t\t\t\t\t\t\tif ($optionValue == $v)\n//\t\t\t\t\t\t\t\t$selected = true;\n//\t\t\t\t\t\t\telse if ($optionText == $v && $optionTextLenght == mb_strlen($v))\n//\t\t\t\t\t\t\t\t$selected = true;\n\t\t\t\t\t\tif ($selected)\n\t\t\t\t\t\t\t$option->attr('selected', 'selected');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t$option->removeAttr('selected');\n\t\t\t\t\t}\n\t\t\t\t} else if ($node->get(0)->tagName == 'textarea')\n\t\t\t\t\t$node->markup($val);\n\t\t\t\telse\n\t\t\t\t\t$node->attr('value', $val);\n\t\t\t}\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function andSelf() {\n\t\tif ( $this->previous )\n\t\t\t$this->elements = array_merge($this->elements, $this->previous->elements);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function addClass( $className) {\n\t\tif (! $className)\n\t\t\treturn $this;\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tif (! $this->is(\".$className\", $node))\n\t\t\t\t$node->setAttribute(\n\t\t\t\t\t'class',\n\t\t\t\t\ttrim($node->getAttribute('class').' '.$className)\n\t\t\t\t);\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function addClassPHP( $className) {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\t\t$classes = $node->getAttribute('class');\n\t\t\t\t$newValue = $classes\n\t\t\t\t\t? $classes.' <'.'?php '.$className.' ?'.'>'\n\t\t\t\t\t: '<'.'?php '.$className.' ?'.'>';\n\t\t\t\t$node->setAttribute('class', $newValue);\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param\tstring\t$className\n\t * @return\tbool\n\t */\n\tpublic function hasClass($className) {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tif ( $this->is(\".$className\", $node))\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function removeClass($className) {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\t$classes = explode( ' ', $node->getAttribute('class'));\n\t\t\tif ( in_array($className, $classes)) {\n\t\t\t\t$classes = array_diff($classes, array($className));\n\t\t\t\tif ( $classes )\n\t\t\t\t\t$node->setAttribute('class', implode(' ', $classes));\n\t\t\t\telse\n\t\t\t\t\t$node->removeAttribute('class');\n\t\t\t}\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function toggleClass($className) {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\tif ( $this->is( $node, '.'.$className ))\n\t\t\t\t$this->removeClass($className);\n\t\t\telse\n\t\t\t\t$this->addClass($className);\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Proper name without underscore (just ->empty()) also works.\n\t *\n\t * Removes all child nodes from the set of matched elements.\n\t *\n\t * Example:\n\t * pq(\"p\")._empty()\n\t *\n\t * HTML:\n\t * <p>Hello, <span>Person</span> <a href=\"#\">and person</a></p>\n\t *\n\t * Result:\n\t * [ <p></p> ]\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @access private\n\t */\n\tpublic function _empty() {\n\t\tforeach($this->stack(1) as $node) {\n\t\t\t// thx to 'dave at dgx dot cz'\n\t\t\t$node->nodeValue = '';\n\t\t}\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param array|string $callback Expects $node as first param, $index as second\n\t * @param array $scope External variables passed to callback. Use compact('varName1', 'varName2'...) and extract($scope)\n\t * @param array $arg1 Will ba passed as third and futher args to callback.\n\t * @param array $arg2 Will ba passed as fourth and futher args to callback, and so on...\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function each($callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\t$paramStructure = null;\n\t\tif (func_num_args() > 1) {\n\t\t\t$paramStructure = func_get_args();\n\t\t\t$paramStructure = array_slice($paramStructure, 1);\n\t\t}\n\t\tforeach($this->elements as $v)\n\t\t\tphpQuery::callbackRun($callback, array($v), $paramStructure);\n\t\treturn $this;\n\t}\n\t/**\n\t * Run callback on actual object.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function callback($callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\t$params = func_get_args();\n\t\t$params[0] = $this;\n\t\tphpQuery::callbackRun($callback, $params);\n\t\treturn $this;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @todo add $scope and $args as in each() ???\n\t */\n\tpublic function map($callback, $param1 = null, $param2 = null, $param3 = null) {\n//\t\t$stack = array();\n////\t\tforeach($this->newInstance() as $node) {\n//\t\tforeach($this->newInstance() as $node) {\n//\t\t\t$result = call_user_func($callback, $node);\n//\t\t\tif ($result)\n//\t\t\t\t$stack[] = $result;\n//\t\t}\n\t\t$params = func_get_args();\n\t\tarray_unshift($params, $this->elements);\n\t\treturn $this->newInstance(\n\t\t\tcall_user_func_array(array('phpQuery', 'map'), $params)\n//\t\t\tphpQuery::map($this->elements, $callback)\n\t\t);\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param <type> $key\n\t * @param <type> $value\n\t */\n\tpublic function data($key, $value = null) {\n\t\tif (! isset($value)) {\n\t\t\t// TODO? implement specific jQuery behavior od returning parent values\n\t\t\t// is child which we look up doesn't exist\n\t\t\treturn phpQuery::data($this->get(0), $key, $value, $this->getDocumentID());\n\t\t} else {\n\t\t\tforeach($this as $node)\n\t\t\t\tphpQuery::data($node, $key, $value, $this->getDocumentID());\n\t\t\treturn $this;\n\t\t}\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param <type> $key\n\t */\n\tpublic function removeData($key) {\n\t\tforeach($this as $node)\n\t\t\tphpQuery::removeData($node, $key, $this->getDocumentID());\n\t\treturn $this;\n\t}\n\t// INTERFACE IMPLEMENTATIONS\n\n\t// ITERATOR INTERFACE\n\t/**\n   * @access private\n\t */\n\tpublic function rewind(){\n\t\t$this->debug('iterating foreach');\n//\t\tphpQuery::selectDocument($this->getDocumentID());\n\t\t$this->elementsBackup = $this->elements;\n\t\t$this->elementsInterator = $this->elements;\n\t\t$this->valid = isset( $this->elements[0] )\n\t\t\t? 1 : 0;\n// \t\t$this->elements = $this->valid\n// \t\t\t? array($this->elements[0])\n// \t\t\t: array();\n\t\t$this->current = 0;\n\t}\n\t/**\n   * @access private\n\t */\n\tpublic function current(){\n\t\treturn $this->elementsInterator[ $this->current ];\n\t}\n\t/**\n   * @access private\n\t */\n\tpublic function key(){\n\t\treturn $this->current;\n\t}\n\t/**\n\t * Double-function method.\n\t *\n\t * First: main iterator interface method.\n\t * Second: Returning next sibling, alias for _next().\n\t *\n\t * Proper functionality is choosed automagicaly.\n\t *\n\t * @see phpQueryObject::_next()\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic function next($cssSelector = null){\n//\t\tif ($cssSelector || $this->valid)\n//\t\t\treturn $this->_next($cssSelector);\n\t\t$this->valid = isset( $this->elementsInterator[ $this->current+1 ] )\n\t\t\t? true\n\t\t\t: false;\n\t\tif (! $this->valid && $this->elementsInterator) {\n\t\t\t$this->elementsInterator = null;\n\t\t} else if ($this->valid) {\n\t\t\t$this->current++;\n\t\t} else {\n\t\t\treturn $this->_next($cssSelector);\n\t\t}\n\t}\n\t/**\n   * @access private\n\t */\n\tpublic function valid(){\n\t\treturn $this->valid;\n\t}\n\t// ITERATOR INTERFACE END\n\t// ARRAYACCESS INTERFACE\n\t/**\n   * @access private\n\t */\n\tpublic function offsetExists($offset) {\n\t\treturn $this->find($offset)->size() > 0;\n\t}\n\t/**\n   * @access private\n\t */\n\tpublic function offsetGet($offset) {\n\t\treturn $this->find($offset);\n\t}\n\t/**\n   * @access private\n\t */\n\tpublic function offsetSet($offset, $value) {\n//\t\t$this->find($offset)->replaceWith($value);\n\t\t$this->find($offset)->html($value);\n\t}\n\t/**\n   * @access private\n\t */\n\tpublic function offsetUnset($offset) {\n\t\t// empty\n\t\tthrow new Exception(\"Can't do unset, use array interface only for calling queries and replacing HTML.\");\n\t}\n\t// ARRAYACCESS INTERFACE END\n\t/**\n\t * Returns node's XPath.\n\t *\n\t * @param unknown_type $oneNode\n\t * @return string\n\t * @TODO use native getNodePath is avaible\n\t * @access private\n\t */\n\tprotected function getNodeXpath($oneNode = null, $namespace = null) {\n\t\t$return = array();\n\t\t$loop = $oneNode\n\t\t\t? array($oneNode)\n\t\t\t: $this->elements;\n//\t\tif ($namespace)\n//\t\t\t$namespace .= ':';\n\t\tforeach($loop as $node) {\n\t\t\tif ($node instanceof DOMDOCUMENT) {\n\t\t\t\t$return[] = '';\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$xpath = array();\n\t\t\twhile(! ($node instanceof DOMDOCUMENT)) {\n\t\t\t\t$i = 1;\n\t\t\t\t$sibling = $node;\n\t\t\t\twhile($sibling->previousSibling) {\n\t\t\t\t\t$sibling = $sibling->previousSibling;\n\t\t\t\t\t$isElement = $sibling instanceof DOMELEMENT;\n\t\t\t\t\tif ($isElement && $sibling->tagName == $node->tagName)\n\t\t\t\t\t\t$i++;\n\t\t\t\t}\n\t\t\t\t$xpath[] = $this->isXML()\n\t\t\t\t\t? \"*[local-name()='{$node->tagName}'][{$i}]\"\n\t\t\t\t\t: \"{$node->tagName}[{$i}]\";\n\t\t\t\t$node = $node->parentNode;\n\t\t\t}\n\t\t\t$xpath = implode('/', array_reverse($xpath));\n\t\t\t$return[] = '/'.$xpath;\n\t\t}\n\t\treturn $oneNode\n\t\t\t? $return[0]\n\t\t\t: $return;\n\t}\n\t// HELPERS\n\tpublic function whois($oneNode = null) {\n\t\t$return = array();\n\t\t$loop = $oneNode\n\t\t\t? array( $oneNode )\n\t\t\t: $this->elements;\n\t\tforeach($loop as $node) {\n\t\t\tif (isset($node->tagName)) {\n\t\t\t\t$tag = in_array($node->tagName, array('php', 'js'))\n\t\t\t\t\t? strtoupper($node->tagName)\n\t\t\t\t\t: $node->tagName;\n\t\t\t\t$return[] = $tag\n\t\t\t\t\t.($node->getAttribute('id')\n\t\t\t\t\t\t? '#'.$node->getAttribute('id'):'')\n\t\t\t\t\t.($node->getAttribute('class')\n\t\t\t\t\t\t? '.'.implode('.', explode(' ', $node->getAttribute('class'))):'')\n\t\t\t\t\t.($node->getAttribute('name')\n\t\t\t\t\t\t? '[name=\"'.$node->getAttribute('name').'\"]':'')\n\t\t\t\t\t.($node->getAttribute('value') && strpos($node->getAttribute('value'), '<'.'?php') === false\n\t\t\t\t\t\t? '[value=\"'.substr(str_replace(\"\\n\", '', $node->getAttribute('value')), 0, 15).'\"]':'')\n\t\t\t\t\t.($node->getAttribute('value') && strpos($node->getAttribute('value'), '<'.'?php') !== false\n\t\t\t\t\t\t? '[value=PHP]':'')\n\t\t\t\t\t.($node->getAttribute('selected')\n\t\t\t\t\t\t? '[selected]':'')\n\t\t\t\t\t.($node->getAttribute('checked')\n\t\t\t\t\t\t? '[checked]':'')\n\t\t\t\t;\n\t\t\t} else if ($node instanceof DOMTEXT) {\n\t\t\t\tif (trim($node->textContent))\n\t\t\t\t\t$return[] = 'Text:'.substr(str_replace(\"\\n\", ' ', $node->textContent), 0, 15);\n\t\t\t} else {\n\n\t\t\t}\n\t\t}\n\t\treturn $oneNode && isset($return[0])\n\t\t\t? $return[0]\n\t\t\t: $return;\n\t}\n\t/**\n\t * Dump htmlOuter and preserve chain. Usefull for debugging.\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t *\n\t */\n\tpublic function dump() {\n\t\tprint 'DUMP #'.(phpQuery::$dumpCount++).' ';\n\t\t$debug = phpQuery::$debug;\n\t\tphpQuery::$debug = false;\n//\t\tprint __FILE__.':'.__LINE__.\"\\n\";\n\t\tvar_dump($this->htmlOuter());\n\t\treturn $this;\n\t}\n\tpublic function dumpWhois() {\n\t\tprint 'DUMP #'.(phpQuery::$dumpCount++).' ';\n\t\t$debug = phpQuery::$debug;\n\t\tphpQuery::$debug = false;\n//\t\tprint __FILE__.':'.__LINE__.\"\\n\";\n\t\tvar_dump('whois', $this->whois());\n\t\tphpQuery::$debug = $debug;\n\t\treturn $this;\n\t}\n\tpublic function dumpLength() {\n\t\tprint 'DUMP #'.(phpQuery::$dumpCount++).' ';\n\t\t$debug = phpQuery::$debug;\n\t\tphpQuery::$debug = false;\n//\t\tprint __FILE__.':'.__LINE__.\"\\n\";\n\t\tvar_dump('length', $this->length());\n\t\tphpQuery::$debug = $debug;\n\t\treturn $this;\n\t}\n\tpublic function dumpTree($html = true, $title = true) {\n\t\t$output = $title\n\t\t\t? 'DUMP #'.(phpQuery::$dumpCount++).\" \\n\" : '';\n\t\t$debug = phpQuery::$debug;\n\t\tphpQuery::$debug = false;\n\t\tforeach($this->stack() as $node)\n\t\t\t$output .= $this->__dumpTree($node);\n\t\tphpQuery::$debug = $debug;\n\t\tprint $html\n\t\t\t? nl2br(str_replace(' ', '&nbsp;', $output))\n\t\t\t: $output;\n\t\treturn $this;\n\t}\n\tprivate function __dumpTree($node, $intend = 0) {\n\t\t$whois = $this->whois($node);\n\t\t$return = '';\n\t\tif ($whois)\n\t\t\t$return .= str_repeat(' - ', $intend).$whois.\"\\n\";\n\t\tif (isset($node->childNodes))\n\t\t\tforeach($node->childNodes as $chNode)\n\t\t\t\t$return .= $this->__dumpTree($chNode, $intend+1);\n\t\treturn $return;\n\t}\n\t/**\n\t * Dump htmlOuter and stop script execution. Usefull for debugging.\n\t *\n\t */\n\tpublic function dumpDie() {\n\t\tprint __FILE__.':'.__LINE__;\n\t\tvar_dump($this->htmlOuter());\n\t\tdie();\n\t}\n}\n\n\n// -- Multibyte Compatibility functions ---------------------------------------\n// http://svn.iphonewebdev.com/lace/lib/mb_compat.php\n\n/**\n *  mb_internal_encoding()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_internal_encoding'))\n{\n\tfunction mb_internal_encoding($enc) {return true; }\n}\n\n/**\n *  mb_regex_encoding()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_regex_encoding'))\n{\n\tfunction mb_regex_encoding($enc) {return true; }\n}\n\n/**\n *  mb_strlen()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_strlen'))\n{\n\tfunction mb_strlen($str)\n\t{\n\t\treturn strlen($str);\n\t}\n}\n\n/**\n *  mb_strpos()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_strpos'))\n{\n\tfunction mb_strpos($haystack, $needle, $offset=0)\n\t{\n\t\treturn strpos($haystack, $needle, $offset);\n\t}\n}\n/**\n *  mb_stripos()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_stripos'))\n{\n\tfunction mb_stripos($haystack, $needle, $offset=0)\n\t{\n\t\treturn stripos($haystack, $needle, $offset);\n\t}\n}\n\n/**\n *  mb_substr()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_substr'))\n{\n\tfunction mb_substr($str, $start, $length=0)\n\t{\n\t\treturn substr($str, $start, $length);\n\t}\n}\n\n/**\n *  mb_substr_count()\n *\n *  Included for mbstring pseudo-compatability.\n */\nif (!function_exists('mb_substr_count'))\n{\n\tfunction mb_substr_count($haystack, $needle)\n\t{\n\t\treturn substr_count($haystack, $needle);\n\t}\n}\n\n\n/**\n * Static namespace for phpQuery functions.\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @package phpQuery\n */\nabstract class phpQuery {\n\t/**\n\t * XXX: Workaround for mbstring problems\n\t *\n\t * @var bool\n\t */\n\tpublic static $mbstringSupport = true;\n\tpublic static $debug = false;\n\tpublic static $documents = array();\n\tpublic static $defaultDocumentID = null;\n//\tpublic static $defaultDoctype = 'html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"';\n\t/**\n\t * Applies only to HTML.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic static $defaultDoctype = '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n\"http://www.w3.org/TR/html4/loose.dtd\">';\n\tpublic static $defaultCharset = 'UTF-8';\n\t/**\n\t * Static namespace for plugins.\n\t *\n\t * @var object\n\t */\n\tpublic static $plugins = array();\n\t/**\n\t * List of loaded plugins.\n\t *\n\t * @var unknown_type\n\t */\n\tpublic static $pluginsLoaded = array();\n\tpublic static $pluginsMethods = array();\n\tpublic static $pluginsStaticMethods = array();\n\tpublic static $extendMethods = array();\n\t/**\n\t * @TODO implement\n\t */\n\tpublic static $extendStaticMethods = array();\n\t/**\n\t * Hosts allowed for AJAX connections.\n\t * Dot '.' means $_SERVER['HTTP_HOST'] (if any).\n\t *\n\t * @var array\n\t */\n\tpublic static $ajaxAllowedHosts = array(\n\t\t'.'\n\t);\n\t/**\n\t * AJAX settings.\n\t *\n\t * @var array\n\t * XXX should it be static or not ?\n\t */\n\tpublic static $ajaxSettings = array(\n\t\t'url' => '',//TODO\n\t\t'global' => true,\n\t\t'type' => \"GET\",\n\t\t'timeout' => null,\n\t\t'contentType' => \"application/x-www-form-urlencoded\",\n\t\t'processData' => true,\n//\t\t'async' => true,\n\t\t'data' => null,\n\t\t'username' => null,\n\t\t'password' => null,\n\t\t'accepts' => array(\n\t\t\t'xml' => \"application/xml, text/xml\",\n\t\t\t'html' => \"text/html\",\n\t\t\t'script' => \"text/javascript, application/javascript\",\n\t\t\t'json' => \"application/json, text/javascript\",\n\t\t\t'text' => \"text/plain\",\n\t\t\t'_default' => \"*/*\"\n\t\t)\n\t);\n\tpublic static $lastModified = null;\n\tpublic static $active = 0;\n\tpublic static $dumpCount = 0;\n\t/**\n\t * Multi-purpose function.\n\t * Use pq() as shortcut.\n\t *\n\t * In below examples, $pq is any result of pq(); function.\n\t *\n\t * 1. Import markup into existing document (without any attaching):\n\t * - Import into selected document:\n\t *   pq('<div/>')\t\t\t\t// DOESNT accept text nodes at beginning of input string !\n\t * - Import into document with ID from $pq->getDocumentID():\n\t *   pq('<div/>', $pq->getDocumentID())\n\t * - Import into same document as DOMNode belongs to:\n\t *   pq('<div/>', DOMNode)\n\t * - Import into document from phpQuery object:\n\t *   pq('<div/>', $pq)\n\t *\n\t * 2. Run query:\n\t * - Run query on last selected document:\n\t *   pq('div.myClass')\n\t * - Run query on document with ID from $pq->getDocumentID():\n\t *   pq('div.myClass', $pq->getDocumentID())\n\t * - Run query on same document as DOMNode belongs to and use node(s)as root for query:\n\t *   pq('div.myClass', DOMNode)\n\t * - Run query on document from phpQuery object\n\t *   and use object's stack as root node(s) for query:\n\t *   pq('div.myClass', $pq)\n\t *\n\t * @param string|DOMNode|DOMNodeList|array\t$arg1\tHTML markup, CSS Selector, DOMNode or array of DOMNodes\n\t * @param string|phpQueryObject|DOMNode\t$context\tDOM ID from $pq->getDocumentID(), phpQuery object (determines also query root) or DOMNode (determines also query root)\n\t *\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery|QueryTemplatesPhpQuery|false\n   * phpQuery object or false in case of error.\n\t */\n\tpublic static function pq($arg1, $context = null) {\n\t\tif ($arg1 instanceof DOMNODE && ! isset($context)) {\n\t\t\tforeach(phpQuery::$documents as $documentWrapper) {\n\t\t\t\t$compare = $arg1 instanceof DOMDocument\n\t\t\t\t\t? $arg1 : $arg1->ownerDocument;\n\t\t\t\tif ($documentWrapper->document->isSameNode($compare))\n\t\t\t\t\t$context = $documentWrapper->id;\n\t\t\t}\n\t\t}\n\t\tif (! $context) {\n\t\t\t$domId = self::$defaultDocumentID;\n\t\t\tif (! $domId)\n\t\t\t\tthrow new Exception(\"Can't use last created DOM, because there isn't any. Use phpQuery::newDocument() first.\");\n//\t\t} else if (is_object($context) && ($context instanceof PHPQUERY || is_subclass_of($context, 'phpQueryObject')))\n\t\t} else if (is_object($context) && $context instanceof phpQueryObject)\n\t\t\t$domId = $context->getDocumentID();\n\t\telse if ($context instanceof DOMDOCUMENT) {\n\t\t\t$domId = self::getDocumentID($context);\n\t\t\tif (! $domId) {\n\t\t\t\t//throw new Exception('Orphaned DOMDocument');\n\t\t\t\t$domId = self::newDocument($context)->getDocumentID();\n\t\t\t}\n\t\t} else if ($context instanceof DOMNODE) {\n\t\t\t$domId = self::getDocumentID($context);\n\t\t\tif (! $domId) {\n\t\t\t\tthrow new Exception('Orphaned DOMNode');\n//\t\t\t\t$domId = self::newDocument($context->ownerDocument);\n\t\t\t}\n\t\t} else\n\t\t\t$domId = $context;\n\t\tif ($arg1 instanceof phpQueryObject) {\n//\t\tif (is_object($arg1) && (get_class($arg1) == 'phpQueryObject' || $arg1 instanceof PHPQUERY || is_subclass_of($arg1, 'phpQueryObject'))) {\n\t\t\t/**\n\t\t\t * Return $arg1 or import $arg1 stack if document differs:\n\t\t\t * pq(pq('<div/>'))\n\t\t\t */\n\t\t\tif ($arg1->getDocumentID() == $domId)\n\t\t\t\treturn $arg1;\n\t\t\t$class = get_class($arg1);\n\t\t\t// support inheritance by passing old object to overloaded constructor\n\t\t\t$phpQuery = $class != 'phpQuery'\n\t\t\t\t? new $class($arg1, $domId)\n\t\t\t\t: new phpQueryObject($domId);\n\t\t\t$phpQuery->elements = array();\n\t\t\tforeach($arg1->elements as $node)\n\t\t\t\t$phpQuery->elements[] = $phpQuery->document->importNode($node, true);\n\t\t\treturn $phpQuery;\n\t\t} else if ($arg1 instanceof DOMNODE || (is_array($arg1) && isset($arg1[0]) && $arg1[0] instanceof DOMNODE)) {\n\t\t\t/*\n\t\t\t * Wrap DOM nodes with phpQuery object, import into document when needed:\n\t\t\t * pq(array($domNode1, $domNode2))\n\t\t\t */\n\t\t\t$phpQuery = new phpQueryObject($domId);\n\t\t\tif (!($arg1 instanceof DOMNODELIST) && ! is_array($arg1))\n\t\t\t\t$arg1 = array($arg1);\n\t\t\t$phpQuery->elements = array();\n\t\t\tforeach($arg1 as $node) {\n\t\t\t\t$sameDocument = $node->ownerDocument instanceof DOMDOCUMENT\n\t\t\t\t\t&& ! $node->ownerDocument->isSameNode($phpQuery->document);\n\t\t\t\t$phpQuery->elements[] = $sameDocument\n\t\t\t\t\t? $phpQuery->document->importNode($node, true)\n\t\t\t\t\t: $node;\n\t\t\t}\n\t\t\treturn $phpQuery;\n\t\t} else if (self::isMarkup($arg1)) {\n\t\t\t/**\n\t\t\t * Import HTML:\n\t\t\t * pq('<div/>')\n\t\t\t */\n\t\t\t$phpQuery = new phpQueryObject($domId);\n\t\t\treturn $phpQuery->newInstance(\n\t\t\t\t$phpQuery->documentWrapper->import($arg1)\n\t\t\t);\n\t\t} else {\n\t\t\t/**\n\t\t\t * Run CSS query:\n\t\t\t * pq('div.myClass')\n\t\t\t */\n\t\t\t$phpQuery = new phpQueryObject($domId);\n//\t\t\tif ($context && ($context instanceof PHPQUERY || is_subclass_of($context, 'phpQueryObject')))\n\t\t\tif ($context && $context instanceof phpQueryObject)\n\t\t\t\t$phpQuery->elements = $context->elements;\n\t\t\telse if ($context && $context instanceof DOMNODELIST) {\n\t\t\t\t$phpQuery->elements = array();\n\t\t\t\tforeach($context as $node)\n\t\t\t\t\t$phpQuery->elements[] = $node;\n\t\t\t} else if ($context && $context instanceof DOMNODE)\n\t\t\t\t$phpQuery->elements = array($context);\n\t\t\treturn $phpQuery->find($arg1);\n\t\t}\n\t}\n\t/**\n\t * Sets default document to $id. Document has to be loaded prior\n\t * to using this method.\n\t * $id can be retrived via getDocumentID() or getDocumentIDRef().\n\t *\n\t * @param unknown_type $id\n\t */\n\tpublic static function selectDocument($id) {\n\t\t$id = self::getDocumentID($id);\n\t\tself::debug(\"Selecting document '$id' as default one\");\n\t\tself::$defaultDocumentID = self::getDocumentID($id);\n\t}\n\t/**\n\t * Returns document with id $id or last used as phpQueryObject.\n\t * $id can be retrived via getDocumentID() or getDocumentIDRef().\n\t * Chainable.\n\t *\n\t * @see phpQuery::selectDocument()\n\t * @param unknown_type $id\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function getDocument($id = null) {\n\t\tif ($id)\n\t\t\tphpQuery::selectDocument($id);\n\t\telse\n\t\t\t$id = phpQuery::$defaultDocumentID;\n\t\treturn new phpQueryObject($id);\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocument($markup = null, $contentType = null) {\n\t\tif (! $markup)\n\t\t\t$markup = '';\n\t\t$documentID = phpQuery::createDocumentWrapper($markup, $contentType);\n\t\treturn new phpQueryObject($documentID);\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentHTML($markup = null, $charset = null) {\n\t\t$contentType = $charset\n\t\t\t? \";charset=$charset\"\n\t\t\t: '';\n\t\treturn self::newDocument($markup, \"text/html{$contentType}\");\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentXML($markup = null, $charset = null) {\n\t\t$contentType = $charset\n\t\t\t? \";charset=$charset\"\n\t\t\t: '';\n\t\treturn self::newDocument($markup, \"text/xml{$contentType}\");\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentXHTML($markup = null, $charset = null) {\n\t\t$contentType = $charset\n\t\t\t? \";charset=$charset\"\n\t\t\t: '';\n\t\treturn self::newDocument($markup, \"application/xhtml+xml{$contentType}\");\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentPHP($markup = null, $contentType = \"text/html\") {\n\t\t// TODO pass charset to phpToMarkup if possible (use DOMDocumentWrapper function)\n\t\t$markup = phpQuery::phpToMarkup($markup, self::$defaultCharset);\n\t\treturn self::newDocument($markup, $contentType);\n\t}\n\tpublic static function phpToMarkup($php, $charset = 'utf-8') {\n\t\t$regexes = array(\n\t\t\t'@(<(?!\\\\?)(?:[^>]|\\\\?>)+\\\\w+\\\\s*=\\\\s*)(\\')([^\\']*)<'.'?php?(.*?)(?:\\\\?>)([^\\']*)\\'@s',\n\t\t\t'@(<(?!\\\\?)(?:[^>]|\\\\?>)+\\\\w+\\\\s*=\\\\s*)(\")([^\"]*)<'.'?php?(.*?)(?:\\\\?>)([^\"]*)\"@s',\n\t\t);\n\t\tforeach($regexes as $regex)\n\t\t\twhile (preg_match($regex, $php, $matches)) {\n\t\t\t\t$php = preg_replace_callback(\n\t\t\t\t\t$regex,\n//\t\t\t\t\tcreate_function('$m, $charset = \"'.$charset.'\"',\n//\t\t\t\t\t\t'return $m[1].$m[2]\n//\t\t\t\t\t\t\t.htmlspecialchars(\"<\".\"?php\".$m[4].\"?\".\">\", ENT_QUOTES|ENT_NOQUOTES, $charset)\n//\t\t\t\t\t\t\t.$m[5].$m[2];'\n//\t\t\t\t\t),\n\t\t\t\t\tarray('phpQuery', '_phpToMarkupCallback'),\n\t\t\t\t\t$php\n\t\t\t\t);\n\t\t\t}\n\t\t$regex = '@(^|>[^<]*)+?(<\\?php(.*?)(\\?>))@s';\n//preg_match_all($regex, $php, $matches);\n//var_dump($matches);\n\t\t$php = preg_replace($regex, '\\\\1<php><!-- \\\\3 --></php>', $php);\n\t\treturn $php;\n\t}\n\tpublic static function _phpToMarkupCallback($php, $charset = 'utf-8') {\n\t\treturn $m[1].$m[2]\n\t\t\t.htmlspecialchars(\"<\".\"?php\".$m[4].\"?\".\">\", ENT_QUOTES|ENT_NOQUOTES, $charset)\n\t\t\t.$m[5].$m[2];\n\t}\n\tpublic static function _markupToPHPCallback($m) {\n\t\treturn \"<\".\"?php \".htmlspecialchars_decode($m[1]).\" ?\".\">\";\n\t}\n\t/**\n\t * Converts document markup containing PHP code generated by phpQuery::php()\n\t * into valid (executable) PHP code syntax.\n\t *\n\t * @param string|phpQueryObject $content\n\t * @return string PHP code.\n\t */\n\tpublic static function markupToPHP($content) {\n\t\tif ($content instanceof phpQueryObject)\n\t\t\t$content = $content->markupOuter();\n\t\t/* <php>...</php> to <?php...? > */\n\t\t$content = preg_replace_callback(\n\t\t\t'@<php>\\s*<!--(.*?)-->\\s*</php>@s',\n//\t\t\tcreate_function('$m',\n//\t\t\t\t'return \"<'.'?php \".htmlspecialchars_decode($m[1]).\" ?'.'>\";'\n//\t\t\t),\n\t\t\tarray('phpQuery', '_markupToPHPCallback'),\n\t\t\t$content\n\t\t);\n\t\t/* <node attr='< ?php ? >'> extra space added to save highlighters */\n\t\t$regexes = array(\n\t\t\t'@(<(?!\\\\?)(?:[^>]|\\\\?>)+\\\\w+\\\\s*=\\\\s*)(\\')([^\\']*)(?:&lt;|%3C)\\\\?(?:php)?(.*?)(?:\\\\?(?:&gt;|%3E))([^\\']*)\\'@s',\n\t\t\t'@(<(?!\\\\?)(?:[^>]|\\\\?>)+\\\\w+\\\\s*=\\\\s*)(\")([^\"]*)(?:&lt;|%3C)\\\\?(?:php)?(.*?)(?:\\\\?(?:&gt;|%3E))([^\"]*)\"@s',\n\t\t);\n\t\tforeach($regexes as $regex)\n\t\t\twhile (preg_match($regex, $content))\n\t\t\t\t$content = preg_replace_callback(\n\t\t\t\t\t$regex,\n\t\t\t\t\tfunction ($m) {\n\t\t\t\t\t\treturn $m[1].$m[2].$m[3].\"<?php \"\n\t\t\t\t\t\t\t.str_replace(\n\t\t\t\t\t\t\t\tarray(\"%20\", \"%3E\", \"%09\", \"&#10;\", \"&#9;\", \"%7B\", \"%24\", \"%7D\", \"%22\", \"%5B\", \"%5D\"),\n\t\t\t\t\t\t\t\tarray(\" \", \">\", \"\t\", \"\\n\", \"\t\", \"{\", \"$\", \"}\", '\"', \"[\", \"]\"),\n\t\t\t\t\t\t\t\thtmlspecialchars_decode($m[4])\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.\" ?>\".$m[5].$m[2];\n\t\t\t\t\t},\n\t\t\t\t\t$content\n\t\t\t\t);\n\t\treturn $content;\n\t}\n\t/**\n\t * Creates new document from file $file.\n\t * Chainable.\n\t *\n\t * @param string $file URLs allowed. See File wrapper page at php.net for more supported sources.\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentFile($file, $contentType = null) {\n\t\t$documentID = self::createDocumentWrapper(\n\t\t\tfile_get_contents($file), $contentType\n\t\t);\n\t\treturn new phpQueryObject($documentID);\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentFileHTML($file, $charset = null) {\n\t\t$contentType = $charset\n\t\t\t? \";charset=$charset\"\n\t\t\t: '';\n\t\treturn self::newDocumentFile($file, \"text/html{$contentType}\");\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentFileXML($file, $charset = null) {\n\t\t$contentType = $charset\n\t\t\t? \";charset=$charset\"\n\t\t\t: '';\n\t\treturn self::newDocumentFile($file, \"text/xml{$contentType}\");\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentFileXHTML($file, $charset = null) {\n\t\t$contentType = $charset\n\t\t\t? \";charset=$charset\"\n\t\t\t: '';\n\t\treturn self::newDocumentFile($file, \"application/xhtml+xml{$contentType}\");\n\t}\n\t/**\n\t * Creates new document from markup.\n\t * Chainable.\n\t *\n\t * @param unknown_type $markup\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t */\n\tpublic static function newDocumentFilePHP($file, $contentType = null) {\n\t\treturn self::newDocumentPHP(file_get_contents($file), $contentType);\n\t}\n\t/**\n\t * Reuses existing DOMDocument object.\n\t * Chainable.\n\t *\n\t * @param $document DOMDocument\n\t * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n\t * @TODO support DOMDocument\n\t */\n\tpublic static function loadDocument($document) {\n\t\t// TODO\n\t\tdie('TODO loadDocument');\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param unknown_type $html\n\t * @param unknown_type $domId\n\t * @return unknown New DOM ID\n\t * @todo support PHP tags in input\n\t * @todo support passing DOMDocument object from self::loadDocument\n\t */\n\tprotected static function createDocumentWrapper($html, $contentType = null, $documentID = null) {\n\t\tif (function_exists('domxml_open_mem'))\n\t\t\tthrow new Exception(\"Old PHP4 DOM XML extension detected. phpQuery won't work until this extension is enabled.\");\n//\t\t$id = $documentID\n//\t\t\t? $documentID\n//\t\t\t: md5(microtime());\n\t\t$document = null;\n\t\tif ($html instanceof DOMDOCUMENT) {\n\t\t\tif (self::getDocumentID($html)) {\n\t\t\t\t// document already exists in phpQuery::$documents, make a copy\n\t\t\t\t$document = clone $html;\n\t\t\t} else {\n\t\t\t\t// new document, add it to phpQuery::$documents\n\t\t\t\t$wrapper = new DOMDocumentWrapper($html, $contentType, $documentID);\n\t\t\t}\n\t\t} else {\n\t\t\t$wrapper = new DOMDocumentWrapper($html, $contentType, $documentID);\n\t\t}\n//\t\t$wrapper->id = $id;\n\t\t// bind document\n\t\tphpQuery::$documents[$wrapper->id] = $wrapper;\n\t\t// remember last loaded document\n\t\tphpQuery::selectDocument($wrapper->id);\n\t\treturn $wrapper->id;\n\t}\n\t/**\n\t * Extend class namespace.\n\t *\n\t * @param string|array $target\n\t * @param array $source\n\t * @TODO support string $source\n\t * @return unknown_type\n\t */\n\tpublic static function extend($target, $source) {\n\t\tswitch($target) {\n\t\t\tcase 'phpQueryObject':\n\t\t\t\t$targetRef = &self::$extendMethods;\n\t\t\t\t$targetRef2 = &self::$pluginsMethods;\n\t\t\t\tbreak;\n\t\t\tcase 'phpQuery':\n\t\t\t\t$targetRef = &self::$extendStaticMethods;\n\t\t\t\t$targetRef2 = &self::$pluginsStaticMethods;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Exception(\"Unsupported \\$target type\");\n\t\t}\n\t\tif (is_string($source))\n\t\t\t$source = array($source => $source);\n\t\tforeach($source as $method => $callback) {\n\t\t\tif (isset($targetRef[$method])) {\n//\t\t\t\tthrow new Exception\n\t\t\t\tself::debug(\"Duplicate method '{$method}', can\\'t extend '{$target}'\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isset($targetRef2[$method])) {\n//\t\t\t\tthrow new Exception\n\t\t\t\tself::debug(\"Duplicate method '{$method}' from plugin '{$targetRef2[$method]}',\"\n\t\t\t\t\t.\" can\\'t extend '{$target}'\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$targetRef[$method] = $callback;\n\t\t}\n\t\treturn true;\n\t}\n\t/**\n\t * Extend phpQuery with $class from $file.\n\t *\n\t * @param string $class Extending class name. Real class name can be prepended phpQuery_.\n\t * @param string $file Filename to include. Defaults to \"{$class}.php\".\n\t */\n\tpublic static function plugin($class, $file = null) {\n\t\t// TODO $class checked agains phpQuery_$class\n//\t\tif (strpos($class, 'phpQuery') === 0)\n//\t\t\t$class = substr($class, 8);\n\t\tif (in_array($class, self::$pluginsLoaded))\n\t\t\treturn true;\n\t\tif (! $file)\n\t\t\t$file = $class.'.php';\n\t\t$objectClassExists = class_exists('phpQueryObjectPlugin_'.$class);\n\t\t$staticClassExists = class_exists('phpQueryPlugin_'.$class);\n\t\tif (! $objectClassExists && ! $staticClassExists)\n\t\t\trequire_once($file);\n\t\tself::$pluginsLoaded[] = $class;\n\t\t// static methods\n\t\tif (class_exists('phpQueryPlugin_'.$class)) {\n\t\t\t$realClass = 'phpQueryPlugin_'.$class;\n\t\t\t$vars = get_class_vars($realClass);\n\t\t\t$loop = isset($vars['phpQueryMethods'])\n\t\t\t\t&& ! is_null($vars['phpQueryMethods'])\n\t\t\t\t? $vars['phpQueryMethods']\n\t\t\t\t: get_class_methods($realClass);\n\t\t\tforeach($loop as $method) {\n\t\t\t\tif ($method == '__initialize')\n\t\t\t\t\tcontinue;\n\t\t\t\tif (! is_callable(array($realClass, $method)))\n\t\t\t\t\tcontinue;\n\t\t\t\tif (isset(self::$pluginsStaticMethods[$method])) {\n\t\t\t\t\tthrow new Exception(\"Duplicate method '{$method}' from plugin '{$c}' conflicts with same method from plugin '\".self::$pluginsStaticMethods[$method].\"'\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tself::$pluginsStaticMethods[$method] = $class;\n\t\t\t}\n\t\t\tif (method_exists($realClass, '__initialize'))\n\t\t\t\tcall_user_func_array(array($realClass, '__initialize'), array());\n\t\t}\n\t\t// object methods\n\t\tif (class_exists('phpQueryObjectPlugin_'.$class)) {\n\t\t\t$realClass = 'phpQueryObjectPlugin_'.$class;\n\t\t\t$vars = get_class_vars($realClass);\n\t\t\t$loop = isset($vars['phpQueryMethods'])\n\t\t\t\t&& ! is_null($vars['phpQueryMethods'])\n\t\t\t\t? $vars['phpQueryMethods']\n\t\t\t\t: get_class_methods($realClass);\n\t\t\tforeach($loop as $method) {\n\t\t\t\tif (! is_callable(array($realClass, $method)))\n\t\t\t\t\tcontinue;\n\t\t\t\tif (isset(self::$pluginsMethods[$method])) {\n\t\t\t\t\tthrow new Exception(\"Duplicate method '{$method}' from plugin '{$c}' conflicts with same method from plugin '\".self::$pluginsMethods[$method].\"'\");\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tself::$pluginsMethods[$method] = $class;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\t/**\n\t * Unloades all or specified document from memory.\n\t *\n\t * @param mixed $documentID @see phpQuery::getDocumentID() for supported types.\n\t */\n\tpublic static function unloadDocuments($id = null) {\n\t\tif (isset($id)) {\n\t\t\tif ($id = self::getDocumentID($id))\n\t\t\t\tunset(phpQuery::$documents[$id]);\n\t\t} else {\n\t\t\tforeach(phpQuery::$documents as $k => $v) {\n\t\t\t\tunset(phpQuery::$documents[$k]);\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t * Parses phpQuery object or HTML result against PHP tags and makes them active.\n\t *\n\t * @param phpQuery|string $content\n\t * @deprecated\n\t * @return string\n\t */\n\tpublic static function unsafePHPTags($content) {\n\t\treturn self::markupToPHP($content);\n\t}\n\tpublic static function DOMNodeListToArray($DOMNodeList) {\n\t\t$array = array();\n\t\tif (! $DOMNodeList)\n\t\t\treturn $array;\n\t\tforeach($DOMNodeList as $node)\n\t\t\t$array[] = $node;\n\t\treturn $array;\n\t}\n\t/**\n\t * Checks if $input is HTML string, which has to start with '<'.\n\t *\n\t * @deprecated\n\t * @param String $input\n\t * @return Bool\n\t * @todo still used ?\n\t */\n\tpublic static function isMarkup($input) {\n\t\treturn ! is_array($input) && substr(trim($input), 0, 1) == '<';\n\t}\n\tpublic static function debug($text) {\n\t\tif (self::$debug)\n\t\t\tprint var_dump($text);\n\t}\n\t/**\n\t * Make an AJAX request.\n\t *\n\t * @param array See $options http://docs.jquery.com/Ajax/jQuery.ajax#toptions\n\t * Additional options are:\n\t * 'document' - document for global events, @see phpQuery::getDocumentID()\n\t * 'referer' - implemented\n\t * 'requested_with' - TODO; not implemented (X-Requested-With)\n\t * @return Zend_Http_Client\n\t * @link http://docs.jquery.com/Ajax/jQuery.ajax\n\t *\n\t * @TODO $options['cache']\n\t * @TODO $options['processData']\n\t * @TODO $options['xhr']\n\t * @TODO $options['data'] as string\n\t * @TODO XHR interface\n\t */\n\tpublic static function ajax($options = array(), $xhr = null) {\n\t\t$options = array_merge(\n\t\t\tself::$ajaxSettings, $options\n\t\t);\n\t\t$documentID = isset($options['document'])\n\t\t\t? self::getDocumentID($options['document'])\n\t\t\t: null;\n\t\tif ($xhr) {\n\t\t\t// reuse existing XHR object, but clean it up\n\t\t\t$client = $xhr;\n//\t\t\t$client->setParameterPost(null);\n//\t\t\t$client->setParameterGet(null);\n\t\t\t$client->setAuth(false);\n\t\t\t$client->setHeaders(\"If-Modified-Since\", null);\n\t\t\t$client->setHeaders(\"Referer\", null);\n\t\t\t$client->resetParameters();\n\t\t} else {\n\t\t\t// create new XHR object\n\t\t\trequire_once('Zend/Http/Client.php');\n\t\t\t$client = new Zend_Http_Client();\n\t\t\t$client->setCookieJar();\n\t\t}\n\t\tif (isset($options['timeout']))\n\t\t\t$client->setConfig(array(\n\t\t\t\t'timeout'      => $options['timeout'],\n\t\t\t));\n//\t\t\t'maxredirects' => 0,\n\t\tforeach(self::$ajaxAllowedHosts as $k => $host)\n\t\t\tif ($host == '.' && isset($_SERVER['HTTP_HOST']))\n\t\t\t\tself::$ajaxAllowedHosts[$k] = $_SERVER['HTTP_HOST'];\n\t\t$host = parse_url($options['url'], PHP_URL_HOST);\n\t\tif (! in_array($host, self::$ajaxAllowedHosts)) {\n\t\t\tthrow new Exception(\"Request not permitted, host '$host' not present in \"\n\t\t\t\t.\"phpQuery::\\$ajaxAllowedHosts\");\n\t\t}\n\t\t// JSONP\n\t\t$jsre = \"/=\\\\?(&|$)/\";\n\t\tif (isset($options['dataType']) && $options['dataType'] == 'jsonp') {\n\t\t\t$jsonpCallbackParam = $options['jsonp']\n\t\t\t\t? $options['jsonp'] : 'callback';\n\t\t\tif (strtolower($options['type']) == 'get') {\n\t\t\t\tif (! preg_match($jsre, $options['url'])) {\n\t\t\t\t\t$sep = strpos($options['url'], '?')\n\t\t\t\t\t\t? '&' : '?';\n\t\t\t\t\t$options['url'] .= \"$sep$jsonpCallbackParam=?\";\n\t\t\t\t}\n\t\t\t} else if ($options['data']) {\n\t\t\t\t$jsonp = false;\n\t\t\t\tforeach($options['data'] as $n => $v) {\n\t\t\t\t\tif ($v == '?')\n\t\t\t\t\t\t$jsonp = true;\n\t\t\t\t}\n\t\t\t\tif (! $jsonp) {\n\t\t\t\t\t$options['data'][$jsonpCallbackParam] = '?';\n\t\t\t\t}\n\t\t\t}\n\t\t\t$options['dataType'] = 'json';\n\t\t}\n\t\tif (isset($options['dataType']) && $options['dataType'] == 'json') {\n\t\t\t$jsonpCallback = 'json_'.md5(microtime());\n\t\t\t$jsonpData = $jsonpUrl = false;\n\t\t\tif ($options['data']) {\n\t\t\t\tforeach($options['data'] as $n => $v) {\n\t\t\t\t\tif ($v == '?')\n\t\t\t\t\t\t$jsonpData = $n;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (preg_match($jsre, $options['url']))\n\t\t\t\t$jsonpUrl = true;\n\t\t\tif ($jsonpData !== false || $jsonpUrl) {\n\t\t\t\t// remember callback name for httpData()\n\t\t\t\t$options['_jsonp'] = $jsonpCallback;\n\t\t\t\tif ($jsonpData !== false)\n\t\t\t\t\t$options['data'][$jsonpData] = $jsonpCallback;\n\t\t\t\tif ($jsonpUrl)\n\t\t\t\t\t$options['url'] = preg_replace($jsre, \"=$jsonpCallback\\\\1\", $options['url']);\n\t\t\t}\n\t\t}\n\t\t$client->setUri($options['url']);\n\t\t$client->setMethod(strtoupper($options['type']));\n\t\tif (isset($options['referer']) && $options['referer'])\n\t\t\t$client->setHeaders('Referer', $options['referer']);\n\t\t$client->setHeaders(array(\n//\t\t\t'content-type' => $options['contentType'],\n\t\t\t'User-Agent' => 'Mozilla/5.0 (X11; U; Linux x86; en-US; rv:1.9.0.5) Gecko'\n\t\t\t\t .'/2008122010 Firefox/3.0.5',\n\t \t\t// TODO custom charset\n\t\t\t'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',\n// \t \t\t'Connection' => 'keep-alive',\n// \t\t\t'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\n\t \t\t'Accept-Language' => 'en-us,en;q=0.5',\n\t\t));\n\t\tif ($options['username'])\n\t\t\t$client->setAuth($options['username'], $options['password']);\n\t\tif (isset($options['ifModified']) && $options['ifModified'])\n\t\t\t$client->setHeaders(\"If-Modified-Since\",\n\t\t\t\tself::$lastModified\n\t\t\t\t\t? self::$lastModified\n\t\t\t\t\t: \"Thu, 01 Jan 1970 00:00:00 GMT\"\n\t\t\t);\n\t\t$client->setHeaders(\"Accept\",\n\t\t\tisset($options['dataType'])\n\t\t\t&& isset(self::$ajaxSettings['accepts'][ $options['dataType'] ])\n\t\t\t\t? self::$ajaxSettings['accepts'][ $options['dataType'] ].\", */*\"\n\t\t\t\t: self::$ajaxSettings['accepts']['_default']\n\t\t);\n\t\t// TODO $options['processData']\n\t\tif ($options['data'] instanceof phpQueryObject) {\n\t\t\t$serialized = $options['data']->serializeArray($options['data']);\n\t\t\t$options['data'] = array();\n\t\t\tforeach($serialized as $r)\n\t\t\t\t$options['data'][ $r['name'] ] = $r['value'];\n\t\t}\n\t\tif (strtolower($options['type']) == 'get') {\n\t\t\t$client->setParameterGet($options['data']);\n\t\t} else if (strtolower($options['type']) == 'post') {\n\t\t\t$client->setEncType($options['contentType']);\n\t\t\t$client->setParameterPost($options['data']);\n\t\t}\n\t\tif (self::$active == 0 && $options['global'])\n\t\t\tphpQueryEvents::trigger($documentID, 'ajaxStart');\n\t\tself::$active++;\n\t\t// beforeSend callback\n\t\tif (isset($options['beforeSend']) && $options['beforeSend'])\n\t\t\tphpQuery::callbackRun($options['beforeSend'], array($client));\n\t\t// ajaxSend event\n\t\tif ($options['global'])\n\t\t\tphpQueryEvents::trigger($documentID, 'ajaxSend', array($client, $options));\n\t\tif (phpQuery::$debug) {\n\t\t\tself::debug(\"{$options['type']}: {$options['url']}\\n\");\n\t\t\tself::debug(\"Options: <pre>\".var_export($options, true).\"</pre>\\n\");\n//\t\t\tif ($client->getCookieJar())\n//\t\t\t\tself::debug(\"Cookies: <pre>\".var_export($client->getCookieJar()->getMatchingCookies($options['url']), true).\"</pre>\\n\");\n\t\t}\n\t\t// request\n\t\t$response = $client->request();\n\t\tif (phpQuery::$debug) {\n\t\t\tself::debug('Status: '.$response->getStatus().' / '.$response->getMessage());\n\t\t\tself::debug($client->getLastRequest());\n\t\t\tself::debug($response->getHeaders());\n\t\t}\n\t\tif ($response->isSuccessful()) {\n\t\t\t// XXX tempolary\n\t\t\tself::$lastModified = $response->getHeader('Last-Modified');\n\t\t\t$data = self::httpData($response->getBody(), $options['dataType'], $options);\n\t\t\tif (isset($options['success']) && $options['success'])\n\t\t\t\tphpQuery::callbackRun($options['success'], array($data, $response->getStatus(), $options));\n\t\t\tif ($options['global'])\n\t\t\t\tphpQueryEvents::trigger($documentID, 'ajaxSuccess', array($client, $options));\n\t\t} else {\n\t\t\tif (isset($options['error']) && $options['error'])\n\t\t\t\tphpQuery::callbackRun($options['error'], array($client, $response->getStatus(), $response->getMessage()));\n\t\t\tif ($options['global'])\n\t\t\t\tphpQueryEvents::trigger($documentID, 'ajaxError', array($client, /*$response->getStatus(),*/$response->getMessage(), $options));\n\t\t}\n\t\tif (isset($options['complete']) && $options['complete'])\n\t\t\tphpQuery::callbackRun($options['complete'], array($client, $response->getStatus()));\n\t\tif ($options['global'])\n\t\t\tphpQueryEvents::trigger($documentID, 'ajaxComplete', array($client, $options));\n\t\tif ($options['global'] && ! --self::$active)\n\t\t\tphpQueryEvents::trigger($documentID, 'ajaxStop');\n\t\treturn $client;\n//\t\tif (is_null($domId))\n//\t\t\t$domId = self::$defaultDocumentID ? self::$defaultDocumentID : false;\n//\t\treturn new phpQueryAjaxResponse($response, $domId);\n\t}\n\tprotected static function httpData($data, $type, $options) {\n\t\tif (isset($options['dataFilter']) && $options['dataFilter'])\n\t\t\t$data = self::callbackRun($options['dataFilter'], array($data, $type));\n\t\tif (is_string($data)) {\n\t\t\tif ($type == \"json\") {\n\t\t\t\tif (isset($options['_jsonp']) && $options['_jsonp']) {\n\t\t\t\t\t$data = preg_replace('/^\\s*\\w+\\((.*)\\)\\s*$/s', '$1', $data);\n\t\t\t\t}\n\t\t\t\t$data = self::parseJSON($data);\n\t\t\t}\n\t\t}\n\t\treturn $data;\n\t}\n\t/**\n\t * Enter description here...\n\t *\n\t * @param array|phpQuery $data\n\t *\n\t */\n\tpublic static function param($data) {\n\t\treturn http_build_query($data, null, '&');\n\t}\n\tpublic static function get($url, $data = null, $callback = null, $type = null) {\n\t\tif (!is_array($data)) {\n\t\t\t$callback = $data;\n\t\t\t$data = null;\n\t\t}\n\t\t// TODO some array_values on this shit\n\t\treturn phpQuery::ajax(array(\n\t\t\t'type' => 'GET',\n\t\t\t'url' => $url,\n\t\t\t'data' => $data,\n\t\t\t'success' => $callback,\n\t\t\t'dataType' => $type,\n\t\t));\n\t}\n\tpublic static function post($url, $data = null, $callback = null, $type = null) {\n\t\tif (!is_array($data)) {\n\t\t\t$callback = $data;\n\t\t\t$data = null;\n\t\t}\n\t\treturn phpQuery::ajax(array(\n\t\t\t'type' => 'POST',\n\t\t\t'url' => $url,\n\t\t\t'data' => $data,\n\t\t\t'success' => $callback,\n\t\t\t'dataType' => $type,\n\t\t));\n\t}\n\tpublic static function getJSON($url, $data = null, $callback = null) {\n\t\tif (!is_array($data)) {\n\t\t\t$callback = $data;\n\t\t\t$data = null;\n\t\t}\n\t\t// TODO some array_values on this shit\n\t\treturn phpQuery::ajax(array(\n\t\t\t'type' => 'GET',\n\t\t\t'url' => $url,\n\t\t\t'data' => $data,\n\t\t\t'success' => $callback,\n\t\t\t'dataType' => 'json',\n\t\t));\n\t}\n\tpublic static function ajaxSetup($options) {\n\t\tself::$ajaxSettings = array_merge(\n\t\t\tself::$ajaxSettings,\n\t\t\t$options\n\t\t);\n\t}\n\tpublic static function ajaxAllowHost($host1, $host2 = null, $host3 = null) {\n\t\t$loop = is_array($host1)\n\t\t\t? $host1\n\t\t\t: func_get_args();\n\t\tforeach($loop as $host) {\n\t\t\tif ($host && ! in_array($host, phpQuery::$ajaxAllowedHosts)) {\n\t\t\t\tphpQuery::$ajaxAllowedHosts[] = $host;\n\t\t\t}\n\t\t}\n\t}\n\tpublic static function ajaxAllowURL($url1, $url2 = null, $url3 = null) {\n\t\t$loop = is_array($url1)\n\t\t\t? $url1\n\t\t\t: func_get_args();\n\t\tforeach($loop as $url)\n\t\t\tphpQuery::ajaxAllowHost(parse_url($url, PHP_URL_HOST));\n\t}\n\t/**\n\t * Returns JSON representation of $data.\n\t *\n\t * @static\n\t * @param mixed $data\n\t * @return string\n\t */\n\tpublic static function toJSON($data) {\n\t\tif (function_exists('json_encode'))\n\t\t\treturn json_encode($data);\n\t\trequire_once('Zend/Json/Encoder.php');\n\t\treturn Zend_Json_Encoder::encode($data);\n\t}\n\t/**\n\t * Parses JSON into proper PHP type.\n\t *\n\t * @static\n\t * @param string $json\n\t * @return mixed\n\t */\n\tpublic static function parseJSON($json) {\n\t\tif (function_exists('json_decode')) {\n\t\t\t$return = json_decode(trim($json), true);\n\t\t\t// json_decode and UTF8 issues\n\t\t\tif (isset($return))\n\t\t\t\treturn $return;\n\t\t}\n\t\trequire_once('Zend/Json/Decoder.php');\n\t\treturn Zend_Json_Decoder::decode($json);\n\t}\n\t/**\n\t * Returns source's document ID.\n\t *\n\t * @param $source DOMNode|phpQueryObject\n\t * @return string\n\t */\n\tpublic static function getDocumentID($source) {\n\t\tif ($source instanceof DOMDOCUMENT) {\n\t\t\tforeach(phpQuery::$documents as $id => $document) {\n\t\t\t\tif ($source->isSameNode($document->document))\n\t\t\t\t\treturn $id;\n\t\t\t}\n\t\t} else if ($source instanceof DOMNODE) {\n\t\t\tforeach(phpQuery::$documents as $id => $document) {\n\t\t\t\tif ($source->ownerDocument->isSameNode($document->document))\n\t\t\t\t\treturn $id;\n\t\t\t}\n\t\t} else if ($source instanceof phpQueryObject)\n\t\t\treturn $source->getDocumentID();\n\t\telse if (is_string($source) && isset(phpQuery::$documents[$source]))\n\t\t\treturn $source;\n\t}\n\t/**\n\t * Get DOMDocument object related to $source.\n\t * Returns null if such document doesn't exist.\n\t *\n\t * @param $source DOMNode|phpQueryObject|string\n\t * @return string\n\t */\n\tpublic static function getDOMDocument($source) {\n\t\tif ($source instanceof DOMDOCUMENT)\n\t\t\treturn $source;\n\t\t$source = self::getDocumentID($source);\n\t\treturn $source\n\t\t\t? self::$documents[$id]['document']\n\t\t\t: null;\n\t}\n\n\t// UTILITIES\n\t// http://docs.jquery.com/Utilities\n\n\t/**\n\t *\n\t * @return unknown_type\n\t * @link http://docs.jquery.com/Utilities/jQuery.makeArray\n\t */\n\tpublic static function makeArray($obj) {\n\t\t$array = array();\n\t\tif (is_object($object) && $object instanceof DOMNODELIST) {\n\t\t\tforeach($object as $value)\n\t\t\t\t$array[] = $value;\n\t\t} else if (is_object($object) && ! ($object instanceof Iterator)) {\n\t\t\tforeach(get_object_vars($object) as $name => $value)\n\t\t\t\t$array[0][$name] = $value;\n\t\t} else {\n\t\t\tforeach($object as $name => $value)\n\t\t\t\t$array[0][$name] = $value;\n\t\t}\n\t\treturn $array;\n\t}\n\tpublic static function inArray($value, $array) {\n\t\treturn in_array($value, $array);\n\t}\n\t/**\n\t *\n\t * @param $object\n\t * @param $callback\n\t * @return unknown_type\n\t * @link http://docs.jquery.com/Utilities/jQuery.each\n\t */\n\tpublic static function each($object, $callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\t$paramStructure = null;\n\t\tif (func_num_args() > 2) {\n\t\t\t$paramStructure = func_get_args();\n\t\t\t$paramStructure = array_slice($paramStructure, 2);\n\t\t}\n\t\tif (is_object($object) && ! ($object instanceof Iterator)) {\n\t\t\tforeach(get_object_vars($object) as $name => $value)\n\t\t\t\tphpQuery::callbackRun($callback, array($name, $value), $paramStructure);\n\t\t} else {\n\t\t\tforeach($object as $name => $value)\n\t\t\t\tphpQuery::callbackRun($callback, array($name, $value), $paramStructure);\n\t\t}\n\t}\n\t/**\n\t *\n\t * @link http://docs.jquery.com/Utilities/jQuery.map\n\t */\n\tpublic static function map($array, $callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\t$result = array();\n\t\t$paramStructure = null;\n\t\tif (func_num_args() > 2) {\n\t\t\t$paramStructure = func_get_args();\n\t\t\t$paramStructure = array_slice($paramStructure, 2);\n\t\t}\n\t\tforeach($array as $v) {\n\t\t\t$vv = phpQuery::callbackRun($callback, array($v), $paramStructure);\n//\t\t\t$callbackArgs = $args;\n//\t\t\tforeach($args as $i => $arg) {\n//\t\t\t\t$callbackArgs[$i] = $arg instanceof CallbackParam\n//\t\t\t\t\t? $v\n//\t\t\t\t\t: $arg;\n//\t\t\t}\n//\t\t\t$vv = call_user_func_array($callback, $callbackArgs);\n\t\t\tif (is_array($vv))  {\n\t\t\t\tforeach($vv as $vvv)\n\t\t\t\t\t$result[] = $vvv;\n\t\t\t} else if ($vv !== null) {\n\t\t\t\t$result[] = $vv;\n\t\t\t}\n\t\t}\n\t\treturn $result;\n\t}\n\t/**\n\t *\n\t * @param $callback Callback\n\t * @param $params\n\t * @param $paramStructure\n\t * @return unknown_type\n\t */\n\tpublic static function callbackRun($callback, $params = array(), $paramStructure = null) {\n\t\tif (! $callback)\n\t\t\treturn;\n\t\tif ($callback instanceof CallbackParameterToReference) {\n\t\t\t// TODO support ParamStructure to select which $param push to reference\n\t\t\tif (isset($params[0]))\n\t\t\t\t$callback->callback = $params[0];\n\t\t\treturn true;\n\t\t}\n\t\tif ($callback instanceof Callback) {\n\t\t\t$paramStructure = $callback->params;\n\t\t\t$callback = $callback->callback;\n\t\t}\n\t\tif (! $paramStructure)\n\t\t\treturn call_user_func_array($callback, $params);\n\t\t$p = 0;\n\t\tforeach($paramStructure as $i => $v) {\n\t\t\t$paramStructure[$i] = $v instanceof CallbackParam\n\t\t\t\t? $params[$p++]\n\t\t\t\t: $v;\n\t\t}\n\t\treturn call_user_func_array($callback, $paramStructure);\n\t}\n\t/**\n\t * Merge 2 phpQuery objects.\n\t * @param array $one\n\t * @param array $two\n\t * @protected\n\t * @todo node lists, phpQueryObject\n\t */\n\tpublic static function merge($one, $two) {\n\t\t$elements = $one->elements;\n\t\tforeach($two->elements as $node) {\n\t\t\t$exists = false;\n\t\t\tforeach($elements as $node2) {\n\t\t\t\tif ($node2->isSameNode($node))\n\t\t\t\t\t$exists = true;\n\t\t\t}\n\t\t\tif (! $exists)\n\t\t\t\t$elements[] = $node;\n\t\t}\n\t\treturn $elements;\n//\t\t$one = $one->newInstance();\n//\t\t$one->elements = $elements;\n//\t\treturn $one;\n\t}\n\t/**\n\t *\n\t * @param $array\n\t * @param $callback\n\t * @param $invert\n\t * @return unknown_type\n\t * @link http://docs.jquery.com/Utilities/jQuery.grep\n\t */\n\tpublic static function grep($array, $callback, $invert = false) {\n\t\t$result = array();\n\t\tforeach($array as $k => $v) {\n\t\t\t$r = call_user_func_array($callback, array($v, $k));\n\t\t\tif ($r === !(bool)$invert)\n\t\t\t\t$result[] = $v;\n\t\t}\n\t\treturn $result;\n\t}\n\tpublic static function unique($array) {\n\t\treturn array_unique($array);\n\t}\n\t/**\n\t *\n\t * @param $function\n\t * @return unknown_type\n\t * @TODO there are problems with non-static methods, second parameter pass it\n\t * \tbut doesnt verify is method is really callable\n\t */\n\tpublic static function isFunction($function) {\n\t\treturn is_callable($function);\n\t}\n\tpublic static function trim($str) {\n\t\treturn trim($str);\n\t}\n\t/* PLUGINS NAMESPACE */\n\t/**\n\t *\n\t * @param $url\n\t * @param $callback\n\t * @param $param1\n\t * @param $param2\n\t * @param $param3\n\t * @return phpQueryObject\n\t */\n\tpublic static function browserGet($url, $callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\tif (self::plugin('WebBrowser')) {\n\t\t\t$params = func_get_args();\n\t\t\treturn self::callbackRun(array(self::$plugins, 'browserGet'), $params);\n\t\t} else {\n\t\t\tself::debug('WebBrowser plugin not available...');\n\t\t}\n\t}\n\t/**\n\t *\n\t * @param $url\n\t * @param $data\n\t * @param $callback\n\t * @param $param1\n\t * @param $param2\n\t * @param $param3\n\t * @return phpQueryObject\n\t */\n\tpublic static function browserPost($url, $data, $callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\tif (self::plugin('WebBrowser')) {\n\t\t\t$params = func_get_args();\n\t\t\treturn self::callbackRun(array(self::$plugins, 'browserPost'), $params);\n\t\t} else {\n\t\t\tself::debug('WebBrowser plugin not available...');\n\t\t}\n\t}\n\t/**\n\t *\n\t * @param $ajaxSettings\n\t * @param $callback\n\t * @param $param1\n\t * @param $param2\n\t * @param $param3\n\t * @return phpQueryObject\n\t */\n\tpublic static function browser($ajaxSettings, $callback, $param1 = null, $param2 = null, $param3 = null) {\n\t\tif (self::plugin('WebBrowser')) {\n\t\t\t$params = func_get_args();\n\t\t\treturn self::callbackRun(array(self::$plugins, 'browser'), $params);\n\t\t} else {\n\t\t\tself::debug('WebBrowser plugin not available...');\n\t\t}\n\t}\n\t/**\n\t *\n\t * @param $code\n\t * @return string\n\t */\n\tpublic static function php($code) {\n\t\treturn self::code('php', $code);\n\t}\n\t/**\n\t *\n\t * @param $type\n\t * @param $code\n\t * @return string\n\t */\n\tpublic static function code($type, $code) {\n\t\treturn \"<$type><!-- \".trim($code).\" --></$type>\";\n\t}\n\n\tpublic static function __callStatic($method, $params) {\n\t\treturn call_user_func_array(\n\t\t\tarray(phpQuery::$plugins, $method),\n\t\t\t$params\n\t\t);\n\t}\n\tprotected static function dataSetupNode($node, $documentID) {\n\t\t// search are return if alredy exists\n\t\tforeach(phpQuery::$documents[$documentID]->dataNodes as $dataNode) {\n\t\t\tif ($node->isSameNode($dataNode))\n\t\t\t\treturn $dataNode;\n\t\t}\n\t\t// if doesn't, add it\n\t\tphpQuery::$documents[$documentID]->dataNodes[] = $node;\n\t\treturn $node;\n\t}\n\tprotected static function dataRemoveNode($node, $documentID) {\n\t\t// search are return if alredy exists\n\t\tforeach(phpQuery::$documents[$documentID]->dataNodes as $k => $dataNode) {\n\t\t\tif ($node->isSameNode($dataNode)) {\n\t\t\t\tunset(self::$documents[$documentID]->dataNodes[$k]);\n\t\t\t\tunset(self::$documents[$documentID]->data[ $dataNode->dataID ]);\n\t\t\t}\n\t\t}\n\t}\n\tpublic static function data($node, $name, $data, $documentID = null) {\n\t\tif (! $documentID)\n\t\t\t// TODO check if this works\n\t\t\t$documentID = self::getDocumentID($node);\n\t\t$document = phpQuery::$documents[$documentID];\n\t\t$node = self::dataSetupNode($node, $documentID);\n\t\tif (! isset($node->dataID))\n\t\t\t$node->dataID = ++phpQuery::$documents[$documentID]->uuid;\n\t\t$id = $node->dataID;\n\t\tif (! isset($document->data[$id]))\n\t\t\t$document->data[$id] = array();\n\t\tif (! is_null($data))\n\t\t\t$document->data[$id][$name] = $data;\n\t\tif ($name) {\n\t\t\tif (isset($document->data[$id][$name]))\n\t\t\t\treturn $document->data[$id][$name];\n\t\t} else\n\t\t\treturn $id;\n\t}\n\tpublic static function removeData($node, $name, $documentID) {\n\t\tif (! $documentID)\n\t\t\t// TODO check if this works\n\t\t\t$documentID = self::getDocumentID($node);\n\t\t$document = phpQuery::$documents[$documentID];\n\t\t$node = self::dataSetupNode($node, $documentID);\n\t\t$id = $node->dataID;\n\t\tif ($name) {\n\t\t\tif (isset($document->data[$id][$name]))\n\t\t\t\tunset($document->data[$id][$name]);\n\t\t\t$name = null;\n\t\t\tforeach($document->data[$id] as $name)\n\t\t\t\tbreak;\n\t\t\tif (! $name)\n\t\t\t\tself::removeData($node, $name, $documentID);\n\t\t} else {\n\t\t\tself::dataRemoveNode($node, $documentID);\n\t\t}\n\t}\n}\n/**\n * Plugins static namespace class.\n *\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @package phpQuery\n * @todo move plugin methods here (as statics)\n */\nclass phpQueryPlugins {\n\tpublic function __call($method, $args) {\n\t\tif (isset(phpQuery::$extendStaticMethods[$method])) {\n\t\t\t$return = call_user_func_array(\n\t\t\t\tphpQuery::$extendStaticMethods[$method],\n\t\t\t\t$args\n\t\t\t);\n\t\t} else if (isset(phpQuery::$pluginsStaticMethods[$method])) {\n\t\t\t$class = phpQuery::$pluginsStaticMethods[$method];\n\t\t\t$realClass = \"phpQueryPlugin_$class\";\n\t\t\t$return = call_user_func_array(\n\t\t\t\tarray($realClass, $method),\n\t\t\t\t$args\n\t\t\t);\n\t\t\treturn isset($return)\n\t\t\t\t? $return\n\t\t\t\t: $this;\n\t\t} else\n\t\t\tthrow new Exception(\"Method '{$method}' doesnt exist\");\n\t}\n}\n/**\n * Shortcut to phpQuery::pq($arg1, $context)\n * Chainable.\n *\n * @see phpQuery::pq()\n * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery\n * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>\n * @package phpQuery\n */\nfunction pq($arg1, $context = null) {\n\t$args = func_get_args();\n\treturn call_user_func_array(\n\t\tarray('phpQuery', 'pq'),\n\t\t$args\n\t);\n}\n// add plugins dir and Zend framework to include path\nset_include_path(\n\tget_include_path()\n\t\t.PATH_SEPARATOR.dirname(__FILE__).'/phpQuery/'\n\t\t.PATH_SEPARATOR.dirname(__FILE__).'/phpQuery/plugins/'\n);\n// why ? no __call nor __get for statics in php...\n// XXX __callStatic will be available in PHP 5.3\nphpQuery::$plugins = new phpQueryPlugins();\n// include bootstrap file (personal library config)\nif (file_exists(dirname(__FILE__).'/phpQuery/bootstrap.php'))\n\trequire_once dirname(__FILE__).'/phpQuery/bootstrap.php';\n"
  },
  {
    "path": "vendor/league/flysystem/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at info+flysystem@frankdejonge.nl. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "vendor/league/flysystem/LICENSE",
    "content": "Copyright (c) 2013-2019 Frank de Jonge\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/league/flysystem/SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported          |\n| ------- | ------------------ |\n| 1.0.x   | :white_check_mark: |\n| 2.0.x   | :x:                |\n\n## Reporting a Vulnerability\n\nWhen you've encountered a security vulnerability, please disclose it securely.\n\nThe security process is described at: \n[https://flysystem.thephpleague.com/docs/security/](https://flysystem.thephpleague.com/docs/security/)\n\n"
  },
  {
    "path": "vendor/league/flysystem/composer.json",
    "content": "{\n    \"name\": \"league/flysystem\",\n    \"type\": \"library\",\n    \"description\": \"Filesystem abstraction: Many filesystems, one API.\",\n    \"keywords\": [\n        \"filesystem\", \"filesystems\", \"files\", \"storage\", \"dropbox\", \"aws\",\n        \"abstraction\", \"s3\", \"ftp\", \"sftp\", \"remote\", \"webdav\",\n        \"file systems\", \"cloud\", \"cloud files\", \"rackspace\", \"copy.com\"\n    ],\n    \"funding\": [\n        {\n            \"type\": \"other\",\n            \"url\": \"https://offset.earth/frankdejonge\"\n        }\n    ],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Frank de Jonge\",\n            \"email\": \"info@frenky.net\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^7.2.5 || ^8.0\",\n        \"ext-fileinfo\": \"*\",\n        \"league/mime-type-detection\": \"^1.3\"\n    },\n    \"require-dev\": {\n        \"phpspec/prophecy\": \"^1.11.1\",\n        \"phpunit/phpunit\": \"^8.5.8\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"League\\\\Flysystem\\\\\": \"src/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"League\\\\Flysystem\\\\Stub\\\\\": \"stub/\"\n        }\n    },\n    \"suggest\": {\n        \"league/flysystem-eventable-filesystem\": \"Allows you to use EventableFilesystem\",\n        \"league/flysystem-rackspace\": \"Allows you to use Rackspace Cloud Files\",\n        \"league/flysystem-azure\": \"Allows you to use Windows Azure Blob storage\",\n        \"league/flysystem-webdav\": \"Allows you to use WebDAV storage\",\n        \"league/flysystem-aws-s3-v2\": \"Allows you to use S3 storage with AWS SDK v2\",\n        \"league/flysystem-aws-s3-v3\": \"Allows you to use S3 storage with AWS SDK v3\",\n        \"spatie/flysystem-dropbox\": \"Allows you to use Dropbox storage\",\n        \"srmklive/flysystem-dropbox-v2\": \"Allows you to use Dropbox storage for PHP 5 applications\",\n        \"league/flysystem-cached-adapter\": \"Flysystem adapter decorator for metadata caching\",\n        \"ext-ftp\": \"Allows you to use FTP server storage\",\n        \"ext-openssl\": \"Allows you to use FTPS server storage\",\n        \"league/flysystem-sftp\": \"Allows you to use SFTP server storage via phpseclib\",\n        \"league/flysystem-ziparchive\": \"Allows you to use ZipArchive adapter\"\n    },\n    \"conflict\": {\n        \"league/flysystem-sftp\": \"<1.0.6\"\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.1-dev\"\n        }\n    },\n    \"scripts\": {\n        \"phpstan\": \"php phpstan.php\"\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/deprecations.md",
    "content": "# Deprecations\n\nThis document lists all the planned deprecations.\n\n## Handlers will be removed in 2.0\n\nThe `Handler` type and associated calls will be removed in version 2.0.\n\n### Upgrade path\n\nYou should create your own implementation for handling OOP usage,\nbut it's recommended to move away from using an OOP-style wrapper entirely.\n\nThe reason for this is that it's too easy for implementation details (for\nyour application this is Flysystem) to leak into the application. The most\nimportant part for Flysystem is that it improves portability and creates a\nsolid boundary between your application core and the infrastructure you use.\nThe OOP-style handling breaks this principle, therefore I want to stop\npromoting it. \n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/AbstractAdapter.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nuse League\\Flysystem\\AdapterInterface;\n\nabstract class AbstractAdapter implements AdapterInterface\n{\n    /**\n     * @var string|null path prefix\n     */\n    protected $pathPrefix;\n\n    /**\n     * @var string\n     */\n    protected $pathSeparator = '/';\n\n    /**\n     * Set the path prefix.\n     *\n     * @param string $prefix\n     *\n     * @return void\n     */\n    public function setPathPrefix($prefix)\n    {\n        $prefix = (string) $prefix;\n\n        if ($prefix === '') {\n            $this->pathPrefix = null;\n\n            return;\n        }\n\n        $this->pathPrefix = rtrim($prefix, '\\\\/') . $this->pathSeparator;\n    }\n\n    /**\n     * Get the path prefix.\n     *\n     * @return string|null path prefix or null if pathPrefix is empty\n     */\n    public function getPathPrefix()\n    {\n        return $this->pathPrefix;\n    }\n\n    /**\n     * Prefix a path.\n     *\n     * @param string $path\n     *\n     * @return string prefixed path\n     */\n    public function applyPathPrefix($path)\n    {\n        return $this->getPathPrefix() . ltrim($path, '\\\\/');\n    }\n\n    /**\n     * Remove a path prefix.\n     *\n     * @param string $path\n     *\n     * @return string path without the prefix\n     */\n    public function removePathPrefix($path)\n    {\n        return substr($path, strlen((string) $this->getPathPrefix()));\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nuse DateTime;\nuse League\\Flysystem\\AdapterInterface;\nuse League\\Flysystem\\Config;\nuse League\\Flysystem\\NotSupportedException;\nuse League\\Flysystem\\SafeStorage;\nuse RuntimeException;\n\nabstract class AbstractFtpAdapter extends AbstractAdapter\n{\n    /**\n     * @var mixed\n     */\n    protected $connection;\n\n    /**\n     * @var string\n     */\n    protected $host;\n\n    /**\n     * @var int\n     */\n    protected $port = 21;\n\n    /**\n     * @var bool\n     */\n    protected $ssl = false;\n\n    /**\n     * @var int\n     */\n    protected $timeout = 90;\n\n    /**\n     * @var bool\n     */\n    protected $passive = true;\n\n    /**\n     * @var string\n     */\n    protected $separator = '/';\n\n    /**\n     * @var string|null\n     */\n    protected $root;\n\n    /**\n     * @var int\n     */\n    protected $permPublic = 0744;\n\n    /**\n     * @var int\n     */\n    protected $permPrivate = 0700;\n\n    /**\n     * @var array\n     */\n    protected $configurable = [];\n\n    /**\n     * @var string\n     */\n    protected $systemType;\n\n    /**\n     * @var SafeStorage\n     */\n    protected $safeStorage;\n\n    /**\n     * True to enable timestamps for FTP servers that return unix-style listings.\n     *\n     * @var bool\n     */\n    protected $enableTimestampsOnUnixListings = false;\n\n    /**\n     * Constructor.\n     *\n     * @param array $config\n     */\n    public function __construct(array $config)\n    {\n        $this->safeStorage = new SafeStorage();\n        $this->setConfig($config);\n    }\n\n    /**\n     * Set the config.\n     *\n     * @param array $config\n     *\n     * @return $this\n     */\n    public function setConfig(array $config)\n    {\n        foreach ($this->configurable as $setting) {\n            if ( ! isset($config[$setting])) {\n                continue;\n            }\n\n            $method = 'set' . ucfirst($setting);\n\n            if (method_exists($this, $method)) {\n                $this->$method($config[$setting]);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Returns the host.\n     *\n     * @return string\n     */\n    public function getHost()\n    {\n        return $this->host;\n    }\n\n    /**\n     * Set the host.\n     *\n     * @param string $host\n     *\n     * @return $this\n     */\n    public function setHost($host)\n    {\n        $this->host = $host;\n\n        return $this;\n    }\n\n    /**\n     * Set the public permission value.\n     *\n     * @param int $permPublic\n     *\n     * @return $this\n     */\n    public function setPermPublic($permPublic)\n    {\n        $this->permPublic = $permPublic;\n\n        return $this;\n    }\n\n    /**\n     * Set the private permission value.\n     *\n     * @param int $permPrivate\n     *\n     * @return $this\n     */\n    public function setPermPrivate($permPrivate)\n    {\n        $this->permPrivate = $permPrivate;\n\n        return $this;\n    }\n\n    /**\n     * Returns the ftp port.\n     *\n     * @return int\n     */\n    public function getPort()\n    {\n        return $this->port;\n    }\n\n    /**\n     * Returns the root folder to work from.\n     *\n     * @return string\n     */\n    public function getRoot()\n    {\n        return $this->root;\n    }\n\n    /**\n     * Set the ftp port.\n     *\n     * @param int|string $port\n     *\n     * @return $this\n     */\n    public function setPort($port)\n    {\n        $this->port = (int) $port;\n\n        return $this;\n    }\n\n    /**\n     * Set the root folder to work from.\n     *\n     * @param string $root\n     *\n     * @return $this\n     */\n    public function setRoot($root)\n    {\n        $this->root = rtrim($root, '\\\\/') . $this->separator;\n\n        return $this;\n    }\n\n    /**\n     * Returns the ftp username.\n     *\n     * @return string username\n     */\n    public function getUsername()\n    {\n        $username = $this->safeStorage->retrieveSafely('username');\n\n        return $username !== null ? $username : 'anonymous';\n    }\n\n    /**\n     * Set ftp username.\n     *\n     * @param string $username\n     *\n     * @return $this\n     */\n    public function setUsername($username)\n    {\n        $this->safeStorage->storeSafely('username', $username);\n\n        return $this;\n    }\n\n    /**\n     * Returns the password.\n     *\n     * @return string password\n     */\n    public function getPassword()\n    {\n        return $this->safeStorage->retrieveSafely('password');\n    }\n\n    /**\n     * Set the ftp password.\n     *\n     * @param string $password\n     *\n     * @return $this\n     */\n    public function setPassword($password)\n    {\n        $this->safeStorage->storeSafely('password', $password);\n\n        return $this;\n    }\n\n    /**\n     * Returns the amount of seconds before the connection will timeout.\n     *\n     * @return int\n     */\n    public function getTimeout()\n    {\n        return $this->timeout;\n    }\n\n    /**\n     * Set the amount of seconds before the connection should timeout.\n     *\n     * @param int $timeout\n     *\n     * @return $this\n     */\n    public function setTimeout($timeout)\n    {\n        $this->timeout = (int) $timeout;\n\n        return $this;\n    }\n\n    /**\n     * Return the FTP system type.\n     *\n     * @return string\n     */\n    public function getSystemType()\n    {\n        return $this->systemType;\n    }\n\n    /**\n     * Set the FTP system type (windows or unix).\n     *\n     * @param string $systemType\n     *\n     * @return $this\n     */\n    public function setSystemType($systemType)\n    {\n        $this->systemType = strtolower($systemType);\n\n        return $this;\n    }\n\n    /**\n     * True to enable timestamps for FTP servers that return unix-style listings.\n     *\n     * @param bool $bool\n     *\n     * @return $this\n     */\n    public function setEnableTimestampsOnUnixListings($bool = false)\n    {\n        $this->enableTimestampsOnUnixListings = $bool;\n\n        return $this;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function listContents($directory = '', $recursive = false)\n    {\n        return $this->listDirectoryContents($directory, $recursive);\n    }\n\n    abstract protected function listDirectoryContents($directory, $recursive = false);\n\n    /**\n     * Normalize a directory listing.\n     *\n     * @param array  $listing\n     * @param string $prefix\n     *\n     * @return array directory listing\n     */\n    protected function normalizeListing(array $listing, $prefix = '')\n    {\n        $base = $prefix;\n        $result = [];\n        $listing = $this->removeDotDirectories($listing);\n\n        while ($item = array_shift($listing)) {\n            if (preg_match('#^.*:$#', $item)) {\n                $base = preg_replace('~^\\./*|:$~', '', $item);\n                continue;\n            }\n\n            $result[] = $this->normalizeObject($item, $base);\n        }\n\n        return $this->sortListing($result);\n    }\n\n    /**\n     * Sort a directory listing.\n     *\n     * @param array $result\n     *\n     * @return array sorted listing\n     */\n    protected function sortListing(array $result)\n    {\n        $compare = function ($one, $two) {\n            return strnatcmp($one['path'], $two['path']);\n        };\n\n        usort($result, $compare);\n\n        return $result;\n    }\n\n    /**\n     * Normalize a file entry.\n     *\n     * @param string $item\n     * @param string $base\n     *\n     * @return array normalized file array\n     *\n     * @throws NotSupportedException\n     */\n    protected function normalizeObject($item, $base)\n    {\n        $systemType = $this->systemType ?: $this->detectSystemType($item);\n\n        if ($systemType === 'unix') {\n            return $this->normalizeUnixObject($item, $base);\n        } elseif ($systemType === 'windows') {\n            return $this->normalizeWindowsObject($item, $base);\n        }\n\n        throw NotSupportedException::forFtpSystemType($systemType);\n    }\n\n    /**\n     * Normalize a Unix file entry.\n     *\n     * Given $item contains:\n     *    '-rw-r--r--   1 ftp      ftp           409 Aug 19 09:01 file1.txt'\n     *\n     * This function will return:\n     * [\n     *   'type' => 'file',\n     *   'path' => 'file1.txt',\n     *   'visibility' => 'public',\n     *   'size' => 409,\n     *   'timestamp' => 1566205260\n     * ]\n     *\n     * @param string $item\n     * @param string $base\n     *\n     * @return array normalized file array\n     */\n    protected function normalizeUnixObject($item, $base)\n    {\n        $item = preg_replace('#\\s+#', ' ', trim($item), 7);\n\n        if (count(explode(' ', $item, 9)) !== 9) {\n            throw new RuntimeException(\"Metadata can't be parsed from item '$item' , not enough parts.\");\n        }\n\n        list($permissions, /* $number */, /* $owner */, /* $group */, $size, $month, $day, $timeOrYear, $name) = explode(' ', $item, 9);\n        $type = $this->detectType($permissions);\n        $path = $base === '' ? $name : $base . $this->separator . $name;\n\n        if ($type === 'dir') {\n            $result = compact('type', 'path');\n            if ($this->enableTimestampsOnUnixListings) {\n                $timestamp = $this->normalizeUnixTimestamp($month, $day, $timeOrYear);\n                $result += compact('timestamp');\n            }\n\n            return $result;\n        }\n\n        $permissions = $this->normalizePermissions($permissions);\n        $visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;\n        $size = (int) $size;\n\n        $result = compact('type', 'path', 'visibility', 'size');\n        if ($this->enableTimestampsOnUnixListings) {\n            $timestamp = $this->normalizeUnixTimestamp($month, $day, $timeOrYear);\n            $result += compact('timestamp');\n        }\n\n        return $result;\n    }\n\n    /**\n     * Only accurate to the minute (current year), or to the day.\n     *\n     * Inadequacies in timestamp accuracy are due to limitations of the FTP 'LIST' command\n     *\n     * Note: The 'MLSD' command is a machine-readable replacement for 'LIST'\n     * but many FTP servers do not support it :(\n     *\n     * @param string $month      e.g. 'Aug'\n     * @param string $day        e.g. '19'\n     * @param string $timeOrYear e.g. '09:01' OR '2015'\n     *\n     * @return int\n     */\n    protected function normalizeUnixTimestamp($month, $day, $timeOrYear)\n    {\n        if (is_numeric($timeOrYear)) {\n            $year = $timeOrYear;\n            $hour = '00';\n            $minute = '00';\n            $seconds = '00';\n        } else {\n            $year = date('Y');\n            list($hour, $minute) = explode(':', $timeOrYear);\n            $seconds = '00';\n        }\n        $dateTime = DateTime::createFromFormat('Y-M-j-G:i:s', \"{$year}-{$month}-{$day}-{$hour}:{$minute}:{$seconds}\");\n\n        return $dateTime->getTimestamp();\n    }\n\n    /**\n     * Normalize a Windows/DOS file entry.\n     *\n     * @param string $item\n     * @param string $base\n     *\n     * @return array normalized file array\n     */\n    protected function normalizeWindowsObject($item, $base)\n    {\n        $item = preg_replace('#\\s+#', ' ', trim($item), 3);\n\n        if (count(explode(' ', $item, 4)) !== 4) {\n            throw new RuntimeException(\"Metadata can't be parsed from item '$item' , not enough parts.\");\n        }\n\n        list($date, $time, $size, $name) = explode(' ', $item, 4);\n        $path = $base === '' ? $name : $base . $this->separator . $name;\n\n        // Check for the correct date/time format\n        $format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';\n        $dt = DateTime::createFromFormat($format, $date . $time);\n        $timestamp = $dt ? $dt->getTimestamp() : (int) strtotime(\"$date $time\");\n\n        if ($size === '<DIR>') {\n            $type = 'dir';\n\n            return compact('type', 'path', 'timestamp');\n        }\n\n        $type = 'file';\n        $visibility = AdapterInterface::VISIBILITY_PUBLIC;\n        $size = (int) $size;\n\n        return compact('type', 'path', 'visibility', 'size', 'timestamp');\n    }\n\n    /**\n     * Get the system type from a listing item.\n     *\n     * @param string $item\n     *\n     * @return string the system type\n     */\n    protected function detectSystemType($item)\n    {\n        return preg_match('/^[0-9]{2,4}-[0-9]{2}-[0-9]{2}/', trim($item)) ? 'windows' : 'unix';\n    }\n\n    /**\n     * Get the file type from the permissions.\n     *\n     * @param string $permissions\n     *\n     * @return string file type\n     */\n    protected function detectType($permissions)\n    {\n        return substr($permissions, 0, 1) === 'd' ? 'dir' : 'file';\n    }\n\n    /**\n     * Normalize a permissions string.\n     *\n     * @param string $permissions\n     *\n     * @return int\n     */\n    protected function normalizePermissions($permissions)\n    {\n        if (is_numeric($permissions)) {\n            return ((int) $permissions) & 0777;\n        }\n\n        // remove the type identifier\n        $permissions = substr($permissions, 1);\n\n        // map the string rights to the numeric counterparts\n        $map = ['-' => '0', 'r' => '4', 'w' => '2', 'x' => '1'];\n        $permissions = strtr($permissions, $map);\n\n        // split up the permission groups\n        $parts = str_split($permissions, 3);\n\n        // convert the groups\n        $mapper = function ($part) {\n            return array_sum(str_split($part));\n        };\n\n        // converts to decimal number\n        return octdec(implode('', array_map($mapper, $parts)));\n    }\n\n    /**\n     * Filter out dot-directories.\n     *\n     * @param array $list\n     *\n     * @return array\n     */\n    public function removeDotDirectories(array $list)\n    {\n        $filter = function ($line) {\n            return $line !== '' && ! preg_match('#.* \\.(\\.)?$|^total#', $line);\n        };\n\n        return array_filter($list, $filter);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function has($path)\n    {\n        return $this->getMetadata($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getSize($path)\n    {\n        return $this->getMetadata($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getVisibility($path)\n    {\n        return $this->getMetadata($path);\n    }\n\n    /**\n     * Ensure a directory exists.\n     *\n     * @param string $dirname\n     */\n    public function ensureDirectory($dirname)\n    {\n        $dirname = (string) $dirname;\n\n        if ($dirname !== '' && ! $this->has($dirname)) {\n            $this->createDir($dirname, new Config());\n        }\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getConnection()\n    {\n        if ( ! $this->isConnected()) {\n            $this->disconnect();\n            $this->connect();\n        }\n\n        return $this->connection;\n    }\n\n    /**\n     * Get the public permission value.\n     *\n     * @return int\n     */\n    public function getPermPublic()\n    {\n        return $this->permPublic;\n    }\n\n    /**\n     * Get the private permission value.\n     *\n     * @return int\n     */\n    public function getPermPrivate()\n    {\n        return $this->permPrivate;\n    }\n\n    /**\n     * Disconnect on destruction.\n     */\n    public function __destruct()\n    {\n        $this->disconnect();\n    }\n\n    /**\n     * Establish a connection.\n     */\n    abstract public function connect();\n\n    /**\n     * Close the connection.\n     */\n    abstract public function disconnect();\n\n    /**\n     * Check if a connection is active.\n     *\n     * @return bool\n     */\n    abstract public function isConnected();\n\n    protected function escapePath($path)\n    {\n        return str_replace(['*', '[', ']'], ['\\\\*', '\\\\[', '\\\\]'], $path);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/CanOverwriteFiles.php",
    "content": "<?php\n\n\nnamespace League\\Flysystem\\Adapter;\n\n/**\n * Adapters that implement this interface let the Filesystem know that files can be overwritten using the write\n * functions and don't need the update function to be called. This can help improve performance when asserts are disabled.\n */\ninterface CanOverwriteFiles\n{\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Ftp.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nuse League\\Flysystem\\Adapter\\Polyfill\\StreamedCopyTrait;\nuse League\\Flysystem\\AdapterInterface;\nuse League\\Flysystem\\Config;\nuse League\\Flysystem\\ConnectionErrorException;\nuse League\\Flysystem\\ConnectionRuntimeException;\nuse League\\Flysystem\\InvalidRootException;\nuse League\\Flysystem\\Util;\nuse League\\Flysystem\\Util\\MimeType;\n\nuse function in_array;\n\nclass Ftp extends AbstractFtpAdapter\n{\n    use StreamedCopyTrait;\n\n    /**\n     * @var int\n     */\n    protected $transferMode = FTP_BINARY;\n\n    /**\n     * @var null|bool\n     */\n    protected $ignorePassiveAddress = null;\n\n    /**\n     * @var bool\n     */\n    protected $recurseManually = false;\n\n    /**\n     * @var bool\n     */\n    protected $utf8 = false;\n\n    /**\n     * @var array\n     */\n    protected $configurable = [\n        'host',\n        'port',\n        'username',\n        'password',\n        'ssl',\n        'timeout',\n        'root',\n        'permPrivate',\n        'permPublic',\n        'passive',\n        'transferMode',\n        'systemType',\n        'ignorePassiveAddress',\n        'recurseManually',\n        'utf8',\n        'enableTimestampsOnUnixListings',\n    ];\n\n    /**\n     * @var bool\n     */\n    protected $isPureFtpd;\n\n    /**\n     * Set the transfer mode.\n     *\n     * @param int $mode\n     *\n     * @return $this\n     */\n    public function setTransferMode($mode)\n    {\n        $this->transferMode = $mode;\n\n        return $this;\n    }\n\n    /**\n     * Set if Ssl is enabled.\n     *\n     * @param bool $ssl\n     *\n     * @return $this\n     */\n    public function setSsl($ssl)\n    {\n        $this->ssl = (bool) $ssl;\n\n        return $this;\n    }\n\n    /**\n     * Set if passive mode should be used.\n     *\n     * @param bool $passive\n     */\n    public function setPassive($passive = true)\n    {\n        $this->passive = $passive;\n    }\n\n    /**\n     * @param bool $ignorePassiveAddress\n     */\n    public function setIgnorePassiveAddress($ignorePassiveAddress)\n    {\n        $this->ignorePassiveAddress = $ignorePassiveAddress;\n    }\n\n    /**\n     * @param bool $recurseManually\n     */\n    public function setRecurseManually($recurseManually)\n    {\n        $this->recurseManually = $recurseManually;\n    }\n\n    /**\n     * @param bool $utf8\n     */\n    public function setUtf8($utf8)\n    {\n        $this->utf8 = (bool) $utf8;\n    }\n\n    /**\n     * Connect to the FTP server.\n     */\n    public function connect()\n    {\n        $tries = 3;\n        start_connecting:\n\n        if ($this->ssl) {\n            $this->connection = @ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());\n        } else {\n            $this->connection = @ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());\n        }\n\n        if ( ! $this->connection) {\n            $tries--;\n\n            if ($tries > 0) goto start_connecting;\n\n            throw new ConnectionRuntimeException('Could not connect to host: ' . $this->getHost() . ', port:' . $this->getPort());\n        }\n\n        $this->login();\n        $this->setUtf8Mode();\n        $this->setConnectionPassiveMode();\n        $this->setConnectionRoot();\n        $this->isPureFtpd = $this->isPureFtpdServer();\n    }\n\n    /**\n     * Set the connection to UTF-8 mode.\n     */\n    protected function setUtf8Mode()\n    {\n        if ($this->utf8) {\n            $response = ftp_raw($this->connection, \"OPTS UTF8 ON\");\n            if (!in_array(substr($response[0], 0, 3), ['200', '202'])) {\n                throw new ConnectionRuntimeException(\n                    'Could not set UTF-8 mode for connection: ' . $this->getHost() . '::' . $this->getPort()\n                );\n            }\n        }\n    }\n\n    /**\n     * Set the connections to passive mode.\n     *\n     * @throws ConnectionRuntimeException\n     */\n    protected function setConnectionPassiveMode()\n    {\n        if (is_bool($this->ignorePassiveAddress) && defined('FTP_USEPASVADDRESS')) {\n            ftp_set_option($this->connection, FTP_USEPASVADDRESS, ! $this->ignorePassiveAddress);\n        }\n\n        if ( ! ftp_pasv($this->connection, $this->passive)) {\n            throw new ConnectionRuntimeException(\n                'Could not set passive mode for connection: ' . $this->getHost() . '::' . $this->getPort()\n            );\n        }\n    }\n\n    /**\n     * Set the connection root.\n     */\n    protected function setConnectionRoot()\n    {\n        $root = $this->getRoot();\n        $connection = $this->connection;\n\n        if ($root && ! ftp_chdir($connection, $root)) {\n            throw new InvalidRootException('Root is invalid or does not exist: ' . $this->getRoot());\n        }\n\n        // Store absolute path for further reference.\n        // This is needed when creating directories and\n        // initial root was a relative path, else the root\n        // would be relative to the chdir'd path.\n        $this->root = ftp_pwd($connection);\n    }\n\n    /**\n     * Login.\n     *\n     * @throws ConnectionRuntimeException\n     */\n    protected function login()\n    {\n        set_error_handler(function () {\n        });\n        $isLoggedIn = ftp_login(\n            $this->connection,\n            $this->getUsername(),\n            $this->getPassword()\n        );\n        restore_error_handler();\n\n        if ( ! $isLoggedIn) {\n            $this->disconnect();\n            throw new ConnectionRuntimeException(\n                'Could not login with connection: ' . $this->getHost() . '::' . $this->getPort(\n                ) . ', username: ' . $this->getUsername()\n            );\n        }\n    }\n\n    /**\n     * Disconnect from the FTP server.\n     */\n    public function disconnect()\n    {\n        if ($this->hasFtpConnection()) {\n            @ftp_close($this->connection);\n        }\n\n        $this->connection = null;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function write($path, $contents, Config $config)\n    {\n        $stream = fopen('php://temp', 'w+b');\n        fwrite($stream, $contents);\n        rewind($stream);\n        $result = $this->writeStream($path, $stream, $config);\n        fclose($stream);\n\n        if ($result === false) {\n            return false;\n        }\n\n        $result['contents'] = $contents;\n        $result['mimetype'] = $config->get('mimetype') ?: Util::guessMimeType($path, $contents);\n\n        return $result;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function writeStream($path, $resource, Config $config)\n    {\n        $this->ensureDirectory(Util::dirname($path));\n\n        if ( ! ftp_fput($this->getConnection(), $path, $resource, $this->transferMode)) {\n            return false;\n        }\n\n        if ($visibility = $config->get('visibility')) {\n            $this->setVisibility($path, $visibility);\n        }\n\n        $type = 'file';\n\n        return compact('type', 'path', 'visibility');\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function update($path, $contents, Config $config)\n    {\n        return $this->write($path, $contents, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function updateStream($path, $resource, Config $config)\n    {\n        return $this->writeStream($path, $resource, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function rename($path, $newpath)\n    {\n        return ftp_rename($this->getConnection(), $path, $newpath);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function delete($path)\n    {\n        return ftp_delete($this->getConnection(), $path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function deleteDir($dirname)\n    {\n        $connection = $this->getConnection();\n        $contents = array_reverse($this->listDirectoryContents($dirname, false));\n\n        foreach ($contents as $object) {\n            if ($object['type'] === 'file') {\n                if ( ! ftp_delete($connection, $object['path'])) {\n                    return false;\n                }\n            } elseif ( ! $this->deleteDir($object['path'])) {\n                return false;\n            }\n        }\n\n        return ftp_rmdir($connection, $dirname);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function createDir($dirname, Config $config)\n    {\n        $connection = $this->getConnection();\n        $directories = explode('/', $dirname);\n\n        foreach ($directories as $directory) {\n            if (false === $this->createActualDirectory($directory, $connection)) {\n                $this->setConnectionRoot();\n\n                return false;\n            }\n\n            ftp_chdir($connection, $directory);\n        }\n\n        $this->setConnectionRoot();\n\n        return ['type' => 'dir', 'path' => $dirname];\n    }\n\n    /**\n     * Create a directory.\n     *\n     * @param string   $directory\n     * @param resource $connection\n     *\n     * @return bool\n     */\n    protected function createActualDirectory($directory, $connection)\n    {\n        // List the current directory\n        $listing = ftp_nlist($connection, '.') ?: [];\n\n        foreach ($listing as $key => $item) {\n            if (preg_match('~^\\./.*~', $item)) {\n                $listing[$key] = substr($item, 2);\n            }\n        }\n\n        if (in_array($directory, $listing, true)) {\n            return true;\n        }\n\n        return (boolean) ftp_mkdir($connection, $directory);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMetadata($path)\n    {\n        if ($path === '') {\n            return ['type' => 'dir', 'path' => ''];\n        }\n\n        if (@ftp_chdir($this->getConnection(), $path) === true) {\n            $this->setConnectionRoot();\n\n            return ['type' => 'dir', 'path' => $path];\n        }\n\n        $listing = $this->ftpRawlist('-A', $path);\n\n        if (empty($listing) || in_array('total 0', $listing, true)) {\n            return false;\n        }\n\n        if (preg_match('/.* not found/', $listing[0])) {\n            return false;\n        }\n\n        if (preg_match('/^total [0-9]*$/', $listing[0])) {\n            array_shift($listing);\n        }\n\n        return $this->normalizeObject($listing[0], '');\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMimetype($path)\n    {\n        if ( ! $metadata = $this->getMetadata($path)) {\n            return false;\n        }\n\n        $metadata['mimetype'] = MimeType::detectByFilename($path);\n\n        return $metadata;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getTimestamp($path)\n    {\n        $timestamp = ftp_mdtm($this->getConnection(), $path);\n\n        return ($timestamp !== -1) ? ['path' => $path, 'timestamp' => $timestamp] : false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function read($path)\n    {\n        if ( ! $object = $this->readStream($path)) {\n            return false;\n        }\n\n        $object['contents'] = stream_get_contents($object['stream']);\n        fclose($object['stream']);\n        unset($object['stream']);\n\n        return $object;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function readStream($path)\n    {\n        $stream = fopen('php://temp', 'w+b');\n        $result = ftp_fget($this->getConnection(), $stream, $path, $this->transferMode);\n        rewind($stream);\n\n        if ( ! $result) {\n            fclose($stream);\n\n            return false;\n        }\n\n        return ['type' => 'file', 'path' => $path, 'stream' => $stream];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function setVisibility($path, $visibility)\n    {\n        $mode = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? $this->getPermPublic() : $this->getPermPrivate();\n\n        if ( ! ftp_chmod($this->getConnection(), $mode, $path)) {\n            return false;\n        }\n\n        return compact('path', 'visibility');\n    }\n\n    /**\n     * @inheritdoc\n     *\n     * @param string $directory\n     */\n    protected function listDirectoryContents($directory, $recursive = true)\n    {\n        if ($recursive && $this->recurseManually) {\n            return $this->listDirectoryContentsRecursive($directory);\n        }\n\n        $options = $recursive ? '-alnR' : '-aln';\n        $listing = $this->ftpRawlist($options, $directory);\n\n        return $listing ? $this->normalizeListing($listing, $directory) : [];\n    }\n\n    /**\n     * @inheritdoc\n     *\n     * @param string $directory\n     */\n    protected function listDirectoryContentsRecursive($directory)\n    {\n        $listing = $this->normalizeListing($this->ftpRawlist('-aln', $directory) ?: [], $directory);\n        $output = [];\n\n        foreach ($listing as $item) {\n            $output[] = $item;\n            if ($item['type'] !== 'dir') {\n                continue;\n            }\n            $output = array_merge($output, $this->listDirectoryContentsRecursive($item['path']));\n        }\n\n        return $output;\n    }\n\n    /**\n     * Check if the connection is open.\n     *\n     * @return bool\n     *\n     * @throws ConnectionErrorException\n     */\n    public function isConnected()\n    {\n        return $this->hasFtpConnection() && $this->getRawExecResponseCode('NOOP') === 200;\n    }\n\n    /**\n     * @return bool\n     */\n    protected function isPureFtpdServer()\n    {\n        $response = ftp_raw($this->connection, 'HELP');\n\n        return stripos(implode(' ', $response), 'Pure-FTPd') !== false;\n    }\n\n    /**\n     * The ftp_rawlist function with optional escaping.\n     *\n     * @param string $options\n     * @param string $path\n     *\n     * @return array\n     */\n    protected function ftpRawlist($options, $path)\n    {\n        $connection = $this->getConnection();\n\n        if ($this->isPureFtpd) {\n            $path = str_replace([' ', '[', ']'], ['\\ ', '\\\\[', '\\\\]'], $path);\n        }\n\n        return ftp_rawlist($connection, $options . ' ' . $this->escapePath($path));\n    }\n\n    private function getRawExecResponseCode($command)\n    {\n        $response = @ftp_raw($this->connection, trim($command));\n\n        return (int) preg_replace('/\\D/', '', implode(' ', $response));\n    }\n\n    private function hasFtpConnection(): bool\n    {\n        return is_resource($this->connection) || $this->connection instanceof \\FTP\\Connection;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Ftpd.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nclass Ftpd extends Ftp\n{\n    /**\n     * @inheritdoc\n     */\n    public function getMetadata($path)\n    {\n        if ($path === '') {\n            return ['type' => 'dir', 'path' => ''];\n        }\n\n        if (@ftp_chdir($this->getConnection(), $path) === true) {\n            $this->setConnectionRoot();\n\n            return ['type' => 'dir', 'path' => $path];\n        }\n\n        $object = ftp_raw($this->getConnection(), 'STAT ' . $this->escapePath($path));\n\n        if ( ! $object || count($object) < 3) {\n            return false;\n        }\n\n        if (substr($object[1], 0, 5) === \"ftpd:\") {\n            return false;\n        }\n\n        return $this->normalizeObject($object[1], '');\n    }\n\n    /**\n     * @inheritdoc\n     */\n    protected function listDirectoryContents($directory, $recursive = true)\n    {\n        $listing = ftp_rawlist($this->getConnection(), $this->escapePath($directory), $recursive);\n\n        if ($listing === false || ( ! empty($listing) && substr($listing[0], 0, 5) === \"ftpd:\")) {\n            return [];\n        }\n\n        return $this->normalizeListing($listing, $directory);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Local.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nuse DirectoryIterator;\nuse FilesystemIterator;\nuse finfo as Finfo;\nuse League\\Flysystem\\Config;\nuse League\\Flysystem\\Exception;\nuse League\\Flysystem\\NotSupportedException;\nuse League\\Flysystem\\UnreadableFileException;\nuse League\\Flysystem\\Util;\nuse LogicException;\nuse RecursiveDirectoryIterator;\nuse RecursiveIteratorIterator;\nuse SplFileInfo;\n\nclass Local extends AbstractAdapter\n{\n    /**\n     * @var int\n     */\n    const SKIP_LINKS = 0001;\n\n    /**\n     * @var int\n     */\n    const DISALLOW_LINKS = 0002;\n\n    /**\n     * @var array\n     */\n    protected static $permissions = [\n        'file' => [\n            'public' => 0644,\n            'private' => 0600,\n        ],\n        'dir' => [\n            'public' => 0755,\n            'private' => 0700,\n        ],\n    ];\n\n    /**\n     * @var string\n     */\n    protected $pathSeparator = DIRECTORY_SEPARATOR;\n\n    /**\n     * @var array\n     */\n    protected $permissionMap;\n\n    /**\n     * @var int\n     */\n    protected $writeFlags;\n\n    /**\n     * @var int\n     */\n    private $linkHandling;\n\n    /**\n     * Constructor.\n     *\n     * @param string $root\n     * @param int    $writeFlags\n     * @param int    $linkHandling\n     * @param array  $permissions\n     *\n     * @throws LogicException\n     */\n    public function __construct($root, $writeFlags = LOCK_EX, $linkHandling = self::DISALLOW_LINKS, array $permissions = [])\n    {\n        $root = is_link($root) ? realpath($root) : $root;\n        $this->permissionMap = array_replace_recursive(static::$permissions, $permissions);\n        $this->ensureDirectory($root);\n\n        if ( ! is_dir($root) || ! is_readable($root)) {\n            throw new LogicException('The root path ' . $root . ' is not readable.');\n        }\n\n        $this->setPathPrefix($root);\n        $this->writeFlags = $writeFlags;\n        $this->linkHandling = $linkHandling;\n    }\n\n    /**\n     * Ensure the root directory exists.\n     *\n     * @param string $root root directory path\n     *\n     * @return void\n     *\n     * @throws Exception in case the root directory can not be created\n     */\n    protected function ensureDirectory($root)\n    {\n        if ( ! is_dir($root)) {\n            $umask = umask(0);\n\n            if ( ! @mkdir($root, $this->permissionMap['dir']['public'], true)) {\n                $mkdirError = error_get_last();\n            }\n\n            umask($umask);\n            clearstatcache(false, $root);\n\n            if ( ! is_dir($root)) {\n                $errorMessage = isset($mkdirError['message']) ? $mkdirError['message'] : '';\n                throw new Exception(sprintf('Impossible to create the root directory \"%s\". %s', $root, $errorMessage));\n            }\n        }\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function has($path)\n    {\n        $location = $this->applyPathPrefix($path);\n\n        return file_exists($location);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function write($path, $contents, Config $config)\n    {\n        $location = $this->applyPathPrefix($path);\n        $this->ensureDirectory(dirname($location));\n\n        if (($size = file_put_contents($location, $contents, $this->writeFlags)) === false) {\n            return false;\n        }\n\n        $type = 'file';\n        $result = compact('contents', 'type', 'size', 'path');\n\n        if ($visibility = $config->get('visibility')) {\n            $result['visibility'] = $visibility;\n            $this->setVisibility($path, $visibility);\n        }\n\n        return $result;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function writeStream($path, $resource, Config $config)\n    {\n        $location = $this->applyPathPrefix($path);\n        $this->ensureDirectory(dirname($location));\n        $stream = fopen($location, 'w+b');\n\n        if ( ! $stream || stream_copy_to_stream($resource, $stream) === false || ! fclose($stream)) {\n            return false;\n        }\n\n        $type = 'file';\n        $result = compact('type', 'path');\n\n        if ($visibility = $config->get('visibility')) {\n            $this->setVisibility($path, $visibility);\n            $result['visibility'] = $visibility;\n        }\n\n        return $result;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function readStream($path)\n    {\n        $location = $this->applyPathPrefix($path);\n        $stream = fopen($location, 'rb');\n\n        return ['type' => 'file', 'path' => $path, 'stream' => $stream];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function updateStream($path, $resource, Config $config)\n    {\n        return $this->writeStream($path, $resource, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function update($path, $contents, Config $config)\n    {\n        $location = $this->applyPathPrefix($path);\n        $size = file_put_contents($location, $contents, $this->writeFlags);\n\n        if ($size === false) {\n            return false;\n        }\n\n        $type = 'file';\n\n        $result = compact('type', 'path', 'size', 'contents');\n\n        if ($visibility = $config->get('visibility')) {\n            $this->setVisibility($path, $visibility);\n            $result['visibility'] = $visibility;\n        }\n\n        return $result;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function read($path)\n    {\n        $location = $this->applyPathPrefix($path);\n        $contents = @file_get_contents($location);\n\n        if ($contents === false) {\n            return false;\n        }\n\n        return ['type' => 'file', 'path' => $path, 'contents' => $contents];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function rename($path, $newpath)\n    {\n        $location = $this->applyPathPrefix($path);\n        $destination = $this->applyPathPrefix($newpath);\n        $parentDirectory = $this->applyPathPrefix(Util::dirname($newpath));\n        $this->ensureDirectory($parentDirectory);\n\n        return rename($location, $destination);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function copy($path, $newpath)\n    {\n        $location = $this->applyPathPrefix($path);\n        $destination = $this->applyPathPrefix($newpath);\n        $this->ensureDirectory(dirname($destination));\n\n        return copy($location, $destination);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function delete($path)\n    {\n        $location = $this->applyPathPrefix($path);\n\n        return @unlink($location);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function listContents($directory = '', $recursive = false)\n    {\n        $result = [];\n        $location = $this->applyPathPrefix($directory);\n\n        if ( ! is_dir($location)) {\n            return [];\n        }\n\n        $iterator = $recursive ? $this->getRecursiveDirectoryIterator($location) : $this->getDirectoryIterator($location);\n\n        foreach ($iterator as $file) {\n            $path = $this->getFilePath($file);\n\n            if (preg_match('#(^|/|\\\\\\\\)\\.{1,2}$#', $path)) {\n                continue;\n            }\n\n            $result[] = $this->normalizeFileInfo($file);\n        }\n\n        unset($iterator);\n\n        return array_filter($result);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMetadata($path)\n    {\n        $location = $this->applyPathPrefix($path);\n        clearstatcache(false, $location);\n        $info = new SplFileInfo($location);\n\n        return $this->normalizeFileInfo($info);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getSize($path)\n    {\n        return $this->getMetadata($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMimetype($path)\n    {\n        $location = $this->applyPathPrefix($path);\n        $finfo = new Finfo(FILEINFO_MIME_TYPE);\n        $mimetype = $finfo->file($location);\n\n        if (in_array($mimetype, ['application/octet-stream', 'inode/x-empty', 'application/x-empty'])) {\n            $mimetype = Util\\MimeType::detectByFilename($location);\n        }\n\n        return ['path' => $path, 'type' => 'file', 'mimetype' => $mimetype];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getTimestamp($path)\n    {\n        return $this->getMetadata($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getVisibility($path)\n    {\n        $location = $this->applyPathPrefix($path);\n        clearstatcache(false, $location);\n        $permissions = octdec(substr(sprintf('%o', fileperms($location)), -4));\n        $type = is_dir($location) ? 'dir' : 'file';\n\n        foreach ($this->permissionMap[$type] as $visibility => $visibilityPermissions) {\n            if ($visibilityPermissions == $permissions) {\n                return compact('path', 'visibility');\n            }\n        }\n\n        $visibility = substr(sprintf('%o', fileperms($location)), -4);\n\n        return compact('path', 'visibility');\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function setVisibility($path, $visibility)\n    {\n        $location = $this->applyPathPrefix($path);\n        $type = is_dir($location) ? 'dir' : 'file';\n        $success = chmod($location, $this->permissionMap[$type][$visibility]);\n\n        if ($success === false) {\n            return false;\n        }\n\n        return compact('path', 'visibility');\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function createDir($dirname, Config $config)\n    {\n        $location = $this->applyPathPrefix($dirname);\n        $umask = umask(0);\n        $visibility = $config->get('visibility', 'public');\n        $return = ['path' => $dirname, 'type' => 'dir'];\n\n        if ( ! is_dir($location)) {\n            if (false === @mkdir($location, $this->permissionMap['dir'][$visibility], true)\n                || false === is_dir($location)) {\n                $return = false;\n            }\n        }\n\n        umask($umask);\n\n        return $return;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function deleteDir($dirname)\n    {\n        $location = $this->applyPathPrefix($dirname);\n\n        if ( ! is_dir($location)) {\n            return false;\n        }\n\n        $contents = $this->getRecursiveDirectoryIterator($location, RecursiveIteratorIterator::CHILD_FIRST);\n\n        /** @var SplFileInfo $file */\n        foreach ($contents as $file) {\n            $this->guardAgainstUnreadableFileInfo($file);\n            $this->deleteFileInfoObject($file);\n        }\n\n        unset($contents);\n\n        return rmdir($location);\n    }\n\n    /**\n     * @param SplFileInfo $file\n     */\n    protected function deleteFileInfoObject(SplFileInfo $file)\n    {\n        switch ($file->getType()) {\n            case 'dir':\n                rmdir($file->getRealPath());\n                break;\n            case 'link':\n                unlink($file->getPathname());\n                break;\n            default:\n                unlink($file->getRealPath());\n        }\n    }\n\n    /**\n     * Normalize the file info.\n     *\n     * @param SplFileInfo $file\n     *\n     * @return array|void\n     *\n     * @throws NotSupportedException\n     */\n    protected function normalizeFileInfo(SplFileInfo $file)\n    {\n        if ( ! $file->isLink()) {\n            return $this->mapFileInfo($file);\n        }\n\n        if ($this->linkHandling & self::DISALLOW_LINKS) {\n            throw NotSupportedException::forLink($file);\n        }\n    }\n\n    /**\n     * Get the normalized path from a SplFileInfo object.\n     *\n     * @param SplFileInfo $file\n     *\n     * @return string\n     */\n    protected function getFilePath(SplFileInfo $file)\n    {\n        $location = $file->getPathname();\n        $path = $this->removePathPrefix($location);\n\n        return trim(str_replace('\\\\', '/', $path), '/');\n    }\n\n    /**\n     * @param string $path\n     * @param int    $mode\n     *\n     * @return RecursiveIteratorIterator\n     */\n    protected function getRecursiveDirectoryIterator($path, $mode = RecursiveIteratorIterator::SELF_FIRST)\n    {\n        return new RecursiveIteratorIterator(\n            new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),\n            $mode\n        );\n    }\n\n    /**\n     * @param string $path\n     *\n     * @return DirectoryIterator\n     */\n    protected function getDirectoryIterator($path)\n    {\n        $iterator = new DirectoryIterator($path);\n\n        return $iterator;\n    }\n\n    /**\n     * @param SplFileInfo $file\n     *\n     * @return array\n     */\n    protected function mapFileInfo(SplFileInfo $file)\n    {\n        $normalized = [\n            'type' => $file->getType(),\n            'path' => $this->getFilePath($file),\n        ];\n\n        $normalized['timestamp'] = $file->getMTime();\n\n        if ($normalized['type'] === 'file') {\n            $normalized['size'] = $file->getSize();\n        }\n\n        return $normalized;\n    }\n\n    /**\n     * @param SplFileInfo $file\n     *\n     * @throws UnreadableFileException\n     */\n    protected function guardAgainstUnreadableFileInfo(SplFileInfo $file)\n    {\n        if ( ! $file->isReadable()) {\n            throw UnreadableFileException::forFileInfo($file);\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/NullAdapter.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nuse League\\Flysystem\\Adapter\\Polyfill\\StreamedCopyTrait;\nuse League\\Flysystem\\Adapter\\Polyfill\\StreamedTrait;\nuse League\\Flysystem\\Config;\n\nclass NullAdapter extends AbstractAdapter\n{\n    use StreamedTrait;\n    use StreamedCopyTrait;\n\n    /**\n     * Check whether a file is present.\n     *\n     * @param string $path\n     *\n     * @return bool\n     */\n    public function has($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function write($path, $contents, Config $config)\n    {\n        $type = 'file';\n        $result = compact('contents', 'type', 'path');\n\n        if ($visibility = $config->get('visibility')) {\n            $result['visibility'] = $visibility;\n        }\n\n        return $result;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function update($path, $contents, Config $config)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function read($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function rename($path, $newpath)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function delete($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function listContents($directory = '', $recursive = false)\n    {\n        return [];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMetadata($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getSize($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMimetype($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getTimestamp($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getVisibility($path)\n    {\n        return false;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function setVisibility($path, $visibility)\n    {\n        return compact('visibility');\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function createDir($dirname, Config $config)\n    {\n        return ['path' => $dirname, 'type' => 'dir'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function deleteDir($dirname)\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Polyfill/NotSupportingVisibilityTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter\\Polyfill;\n\nuse LogicException;\n\ntrait NotSupportingVisibilityTrait\n{\n    /**\n     * Get the visibility of a file.\n     *\n     * @param string $path\n     *\n     * @throws LogicException\n     */\n    public function getVisibility($path)\n    {\n        throw new LogicException(get_class($this) . ' does not support visibility. Path: ' . $path);\n    }\n\n    /**\n     * Set the visibility for a file.\n     *\n     * @param string $path\n     * @param string $visibility\n     *\n     * @throws LogicException\n     */\n    public function setVisibility($path, $visibility)\n    {\n        throw new LogicException(get_class($this) . ' does not support visibility. Path: ' . $path . ', visibility: ' . $visibility);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Polyfill/StreamedCopyTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter\\Polyfill;\n\nuse League\\Flysystem\\Config;\n\ntrait StreamedCopyTrait\n{\n    /**\n     * Copy a file.\n     *\n     * @param string $path\n     * @param string $newpath\n     *\n     * @return bool\n     */\n    public function copy($path, $newpath)\n    {\n        $response = $this->readStream($path);\n\n        if ($response === false || ! is_resource($response['stream'])) {\n            return false;\n        }\n\n        $result = $this->writeStream($newpath, $response['stream'], new Config());\n\n        if ($result !== false && is_resource($response['stream'])) {\n            fclose($response['stream']);\n        }\n\n        return $result !== false;\n    }\n\n    // Required abstract method\n\n    /**\n     * @param string $path\n     *\n     * @return resource\n     */\n    abstract public function readStream($path);\n\n    /**\n     * @param string   $path\n     * @param resource $resource\n     * @param Config   $config\n     *\n     * @return resource\n     */\n    abstract public function writeStream($path, $resource, Config $config);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Polyfill/StreamedReadingTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter\\Polyfill;\n\n/**\n * A helper for adapters that only handle strings to provide read streams.\n */\ntrait StreamedReadingTrait\n{\n    /**\n     * Reads a file as a stream.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     *\n     * @see League\\Flysystem\\ReadInterface::readStream()\n     */\n    public function readStream($path)\n    {\n        if ( ! $data = $this->read($path)) {\n            return false;\n        }\n\n        $stream = fopen('php://temp', 'w+b');\n        fwrite($stream, $data['contents']);\n        rewind($stream);\n        $data['stream'] = $stream;\n        unset($data['contents']);\n\n        return $data;\n    }\n\n    /**\n     * Reads a file.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     *\n     * @see League\\Flysystem\\ReadInterface::read()\n     */\n    abstract public function read($path);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Polyfill/StreamedTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter\\Polyfill;\n\ntrait StreamedTrait\n{\n    use StreamedReadingTrait;\n    use StreamedWritingTrait;\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/Polyfill/StreamedWritingTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter\\Polyfill;\n\nuse League\\Flysystem\\Config;\nuse League\\Flysystem\\Util;\n\ntrait StreamedWritingTrait\n{\n    /**\n     * Stream fallback delegator.\n     *\n     * @param string   $path\n     * @param resource $resource\n     * @param Config   $config\n     * @param string   $fallback\n     *\n     * @return mixed fallback result\n     */\n    protected function stream($path, $resource, Config $config, $fallback)\n    {\n        Util::rewindStream($resource);\n        $contents = stream_get_contents($resource);\n        $fallbackCall = [$this, $fallback];\n\n        return call_user_func($fallbackCall, $path, $contents, $config);\n    }\n\n    /**\n     * Write using a stream.\n     *\n     * @param string   $path\n     * @param resource $resource\n     * @param Config   $config\n     *\n     * @return mixed false or file metadata\n     */\n    public function writeStream($path, $resource, Config $config)\n    {\n        return $this->stream($path, $resource, $config, 'write');\n    }\n\n    /**\n     * Update a file using a stream.\n     *\n     * @param string   $path\n     * @param resource $resource\n     * @param Config   $config   Config object or visibility setting\n     *\n     * @return mixed false of file metadata\n     */\n    public function updateStream($path, $resource, Config $config)\n    {\n        return $this->stream($path, $resource, $config, 'update');\n    }\n\n    // Required abstract methods\n    abstract public function write($pash, $contents, Config $config);\n    abstract public function update($pash, $contents, Config $config);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Adapter/SynologyFtp.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Adapter;\n\nclass SynologyFtp extends Ftpd\n{\n    // This class merely exists because of BC.\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/AdapterInterface.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\ninterface AdapterInterface extends ReadInterface\n{\n    /**\n     * @const  VISIBILITY_PUBLIC  public visibility\n     */\n    const VISIBILITY_PUBLIC = 'public';\n\n    /**\n     * @const  VISIBILITY_PRIVATE  private visibility\n     */\n    const VISIBILITY_PRIVATE = 'private';\n\n    /**\n     * Write a new file.\n     *\n     * @param string $path\n     * @param string $contents\n     * @param Config $config   Config object\n     *\n     * @return array|false false on failure file meta data on success\n     */\n    public function write($path, $contents, Config $config);\n\n    /**\n     * Write a new file using a stream.\n     *\n     * @param string   $path\n     * @param resource $resource\n     * @param Config   $config   Config object\n     *\n     * @return array|false false on failure file meta data on success\n     */\n    public function writeStream($path, $resource, Config $config);\n\n    /**\n     * Update a file.\n     *\n     * @param string $path\n     * @param string $contents\n     * @param Config $config   Config object\n     *\n     * @return array|false false on failure file meta data on success\n     */\n    public function update($path, $contents, Config $config);\n\n    /**\n     * Update a file using a stream.\n     *\n     * @param string   $path\n     * @param resource $resource\n     * @param Config   $config   Config object\n     *\n     * @return array|false false on failure file meta data on success\n     */\n    public function updateStream($path, $resource, Config $config);\n\n    /**\n     * Rename a file.\n     *\n     * @param string $path\n     * @param string $newpath\n     *\n     * @return bool\n     */\n    public function rename($path, $newpath);\n\n    /**\n     * Copy a file.\n     *\n     * @param string $path\n     * @param string $newpath\n     *\n     * @return bool\n     */\n    public function copy($path, $newpath);\n\n    /**\n     * Delete a file.\n     *\n     * @param string $path\n     *\n     * @return bool\n     */\n    public function delete($path);\n\n    /**\n     * Delete a directory.\n     *\n     * @param string $dirname\n     *\n     * @return bool\n     */\n    public function deleteDir($dirname);\n\n    /**\n     * Create a directory.\n     *\n     * @param string $dirname directory name\n     * @param Config $config\n     *\n     * @return array|false\n     */\n    public function createDir($dirname, Config $config);\n\n    /**\n     * Set the visibility for a file.\n     *\n     * @param string $path\n     * @param string $visibility\n     *\n     * @return array|false file meta data\n     */\n    public function setVisibility($path, $visibility);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Config.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nclass Config\n{\n    /**\n     * @var array\n     */\n    protected $settings = [];\n\n    /**\n     * @var Config|null\n     */\n    protected $fallback;\n\n    /**\n     * Constructor.\n     *\n     * @param array $settings\n     */\n    public function __construct(array $settings = [])\n    {\n        $this->settings = $settings;\n    }\n\n    /**\n     * Get a setting.\n     *\n     * @param string $key\n     * @param mixed  $default\n     *\n     * @return mixed config setting or default when not found\n     */\n    public function get($key, $default = null)\n    {\n        if ( ! array_key_exists($key, $this->settings)) {\n            return $this->getDefault($key, $default);\n        }\n\n        return $this->settings[$key];\n    }\n\n    /**\n     * Check if an item exists by key.\n     *\n     * @param string $key\n     *\n     * @return bool\n     */\n    public function has($key)\n    {\n        if (array_key_exists($key, $this->settings)) {\n            return true;\n        }\n\n        return $this->fallback instanceof Config\n            ? $this->fallback->has($key)\n            : false;\n    }\n\n    /**\n     * Try to retrieve a default setting from a config fallback.\n     *\n     * @param string $key\n     * @param mixed  $default\n     *\n     * @return mixed config setting or default when not found\n     */\n    protected function getDefault($key, $default)\n    {\n        if ( ! $this->fallback) {\n            return $default;\n        }\n\n        return $this->fallback->get($key, $default);\n    }\n\n    /**\n     * Set a setting.\n     *\n     * @param string $key\n     * @param mixed  $value\n     *\n     * @return $this\n     */\n    public function set($key, $value)\n    {\n        $this->settings[$key] = $value;\n\n        return $this;\n    }\n\n    /**\n     * Set the fallback.\n     *\n     * @param Config $fallback\n     *\n     * @return $this\n     */\n    public function setFallback(Config $fallback)\n    {\n        $this->fallback = $fallback;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/ConfigAwareTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\n/**\n * @internal\n */\ntrait ConfigAwareTrait\n{\n    /**\n     * @var Config\n     */\n    protected $config;\n\n    /**\n     * Set the config.\n     *\n     * @param Config|array|null $config\n     */\n    protected function setConfig($config)\n    {\n        $this->config = $config ? Util::ensureConfig($config) : new Config;\n    }\n\n    /**\n     * Get the Config.\n     *\n     * @return Config config object\n     */\n    public function getConfig()\n    {\n        return $this->config;\n    }\n\n    /**\n     * Convert a config array to a Config object with the correct fallback.\n     *\n     * @param array $config\n     *\n     * @return Config\n     */\n    protected function prepareConfig(array $config)\n    {\n        $config = new Config($config);\n        $config->setFallback($this->getConfig());\n\n        return $config;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/ConnectionErrorException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse ErrorException;\n\nclass ConnectionErrorException extends ErrorException implements FilesystemException\n{\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/ConnectionRuntimeException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse RuntimeException;\n\nclass ConnectionRuntimeException extends RuntimeException implements FilesystemException\n{\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/CorruptedPathDetected.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse LogicException;\n\nclass CorruptedPathDetected extends LogicException implements FilesystemException\n{\n    /**\n     * @param string $path\n     * @return CorruptedPathDetected\n     */\n    public static function forPath($path)\n    {\n        return new CorruptedPathDetected(\"Corrupted path detected: \" . $path);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Directory.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\n/**\n * @deprecated\n */\nclass Directory extends Handler\n{\n    /**\n     * Delete the directory.\n     *\n     * @return bool\n     */\n    public function delete()\n    {\n        return $this->filesystem->deleteDir($this->path);\n    }\n\n    /**\n     * List the directory contents.\n     *\n     * @param bool $recursive\n     *\n     * @return array|bool directory contents or false\n     */\n    public function getContents($recursive = false)\n    {\n        return $this->filesystem->listContents($this->path, $recursive);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Exception.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nclass Exception extends \\Exception implements FilesystemException\n{\n    //\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/File.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\n/**\n * @deprecated\n */\nclass File extends Handler\n{\n    /**\n     * Check whether the file exists.\n     *\n     * @return bool\n     */\n    public function exists()\n    {\n        return $this->filesystem->has($this->path);\n    }\n\n    /**\n     * Read the file.\n     *\n     * @return string|false file contents\n     */\n    public function read()\n    {\n        return $this->filesystem->read($this->path);\n    }\n\n    /**\n     * Read the file as a stream.\n     *\n     * @return resource|false file stream\n     */\n    public function readStream()\n    {\n        return $this->filesystem->readStream($this->path);\n    }\n\n    /**\n     * Write the new file.\n     *\n     * @param string $content\n     *\n     * @return bool success boolean\n     */\n    public function write($content)\n    {\n        return $this->filesystem->write($this->path, $content);\n    }\n\n    /**\n     * Write the new file using a stream.\n     *\n     * @param resource $resource\n     *\n     * @return bool success boolean\n     */\n    public function writeStream($resource)\n    {\n        return $this->filesystem->writeStream($this->path, $resource);\n    }\n\n    /**\n     * Update the file contents.\n     *\n     * @param string $content\n     *\n     * @return bool success boolean\n     */\n    public function update($content)\n    {\n        return $this->filesystem->update($this->path, $content);\n    }\n\n    /**\n     * Update the file contents with a stream.\n     *\n     * @param resource $resource\n     *\n     * @return bool success boolean\n     */\n    public function updateStream($resource)\n    {\n        return $this->filesystem->updateStream($this->path, $resource);\n    }\n\n    /**\n     * Create the file or update if exists.\n     *\n     * @param string $content\n     *\n     * @return bool success boolean\n     */\n    public function put($content)\n    {\n        return $this->filesystem->put($this->path, $content);\n    }\n\n    /**\n     * Create the file or update if exists using a stream.\n     *\n     * @param resource $resource\n     *\n     * @return bool success boolean\n     */\n    public function putStream($resource)\n    {\n        return $this->filesystem->putStream($this->path, $resource);\n    }\n\n    /**\n     * Rename the file.\n     *\n     * @param string $newpath\n     *\n     * @return bool success boolean\n     */\n    public function rename($newpath)\n    {\n        if ($this->filesystem->rename($this->path, $newpath)) {\n            $this->path = $newpath;\n\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Copy the file.\n     *\n     * @param string $newpath\n     *\n     * @return File|false new file or false\n     */\n    public function copy($newpath)\n    {\n        if ($this->filesystem->copy($this->path, $newpath)) {\n            return new File($this->filesystem, $newpath);\n        }\n\n        return false;\n    }\n\n    /**\n     * Get the file's timestamp.\n     *\n     * @return string|false The timestamp or false on failure.\n     */\n    public function getTimestamp()\n    {\n        return $this->filesystem->getTimestamp($this->path);\n    }\n\n    /**\n     * Get the file's mimetype.\n     *\n     * @return string|false The file mime-type or false on failure.\n     */\n    public function getMimetype()\n    {\n        return $this->filesystem->getMimetype($this->path);\n    }\n\n    /**\n     * Get the file's visibility.\n     *\n     * @return string|false The visibility (public|private) or false on failure.\n     */\n    public function getVisibility()\n    {\n        return $this->filesystem->getVisibility($this->path);\n    }\n\n    /**\n     * Get the file's metadata.\n     *\n     * @return array|false The file metadata or false on failure.\n     */\n    public function getMetadata()\n    {\n        return $this->filesystem->getMetadata($this->path);\n    }\n\n    /**\n     * Get the file size.\n     *\n     * @return int|false The file size or false on failure.\n     */\n    public function getSize()\n    {\n        return $this->filesystem->getSize($this->path);\n    }\n\n    /**\n     * Delete the file.\n     *\n     * @return bool success boolean\n     */\n    public function delete()\n    {\n        return $this->filesystem->delete($this->path);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/FileExistsException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse Exception as BaseException;\n\nclass FileExistsException extends Exception\n{\n    /**\n     * @var string\n     */\n    protected $path;\n\n    /**\n     * Constructor.\n     *\n     * @param string        $path\n     * @param int           $code\n     * @param BaseException $previous\n     */\n    public function __construct($path, $code = 0, BaseException $previous = null)\n    {\n        $this->path = $path;\n\n        parent::__construct('File already exists at path: ' . $this->getPath(), $code, $previous);\n    }\n\n    /**\n     * Get the path which was found.\n     *\n     * @return string\n     */\n    public function getPath()\n    {\n        return $this->path;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/FileNotFoundException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse Exception as BaseException;\n\nclass FileNotFoundException extends Exception\n{\n    /**\n     * @var string\n     */\n    protected $path;\n\n    /**\n     * Constructor.\n     *\n     * @param string     $path\n     * @param int        $code\n     * @param \\Exception $previous\n     */\n    public function __construct($path, $code = 0, BaseException $previous = null)\n    {\n        $this->path = $path;\n\n        parent::__construct('File not found at path: ' . $this->getPath(), $code, $previous);\n    }\n\n    /**\n     * Get the path which was not found.\n     *\n     * @return string\n     */\n    public function getPath()\n    {\n        return $this->path;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Filesystem.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse InvalidArgumentException;\nuse League\\Flysystem\\Adapter\\CanOverwriteFiles;\nuse League\\Flysystem\\Plugin\\PluggableTrait;\nuse League\\Flysystem\\Util\\ContentListingFormatter;\n\n/**\n * @method void        emptyDir(string $dirname)\n * @method array|false getWithMetadata(string $path, string[] $metadata)\n * @method bool        forceCopy(string $path, string $newpath)\n * @method bool        forceRename(string $path, string $newpath)\n * @method array       listFiles(string $path = '', boolean $recursive = false)\n * @method string[]    listPaths(string $path = '', boolean $recursive = false)\n * @method array       listWith(string[] $keys = [], $directory = '', $recursive = false)\n */\nclass Filesystem implements FilesystemInterface\n{\n    use PluggableTrait;\n    use ConfigAwareTrait;\n\n    /**\n     * @var AdapterInterface\n     */\n    protected $adapter;\n\n    /**\n     * Constructor.\n     *\n     * @param AdapterInterface $adapter\n     * @param Config|array     $config\n     */\n    public function __construct(AdapterInterface $adapter, $config = null)\n    {\n        $this->adapter = $adapter;\n        $this->setConfig($config);\n    }\n\n    /**\n     * Get the Adapter.\n     *\n     * @return AdapterInterface adapter\n     */\n    public function getAdapter()\n    {\n        return $this->adapter;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function has($path)\n    {\n        $path = Util::normalizePath($path);\n\n        return strlen($path) === 0 ? false : (bool) $this->getAdapter()->has($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function write($path, $contents, array $config = [])\n    {\n        $path = Util::normalizePath($path);\n        $this->assertAbsent($path);\n        $config = $this->prepareConfig($config);\n\n        return (bool) $this->getAdapter()->write($path, $contents, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function writeStream($path, $resource, array $config = [])\n    {\n        if ( ! is_resource($resource) || get_resource_type($resource) !== 'stream') {\n            throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');\n        }\n\n        $path = Util::normalizePath($path);\n        $this->assertAbsent($path);\n        $config = $this->prepareConfig($config);\n\n        Util::rewindStream($resource);\n\n        return (bool) $this->getAdapter()->writeStream($path, $resource, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function put($path, $contents, array $config = [])\n    {\n        $path = Util::normalizePath($path);\n        $config = $this->prepareConfig($config);\n\n        if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {\n            return (bool) $this->getAdapter()->update($path, $contents, $config);\n        }\n\n        return (bool) $this->getAdapter()->write($path, $contents, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function putStream($path, $resource, array $config = [])\n    {\n        if ( ! is_resource($resource) || get_resource_type($resource) !== 'stream') {\n            throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');\n        }\n\n        $path = Util::normalizePath($path);\n        $config = $this->prepareConfig($config);\n        Util::rewindStream($resource);\n\n        if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {\n            return (bool) $this->getAdapter()->updateStream($path, $resource, $config);\n        }\n\n        return (bool) $this->getAdapter()->writeStream($path, $resource, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function readAndDelete($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n        $contents = $this->read($path);\n\n        if ($contents === false) {\n            return false;\n        }\n\n        $this->delete($path);\n\n        return $contents;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function update($path, $contents, array $config = [])\n    {\n        $path = Util::normalizePath($path);\n        $config = $this->prepareConfig($config);\n\n        $this->assertPresent($path);\n\n        return (bool) $this->getAdapter()->update($path, $contents, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function updateStream($path, $resource, array $config = [])\n    {\n        if ( ! is_resource($resource) || get_resource_type($resource) !== 'stream') {\n            throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');\n        }\n\n        $path = Util::normalizePath($path);\n        $config = $this->prepareConfig($config);\n        $this->assertPresent($path);\n        Util::rewindStream($resource);\n\n        return (bool) $this->getAdapter()->updateStream($path, $resource, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function read($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        if ( ! ($object = $this->getAdapter()->read($path))) {\n            return false;\n        }\n\n        return $object['contents'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function readStream($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        if ( ! $object = $this->getAdapter()->readStream($path)) {\n            return false;\n        }\n\n        return $object['stream'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function rename($path, $newpath)\n    {\n        $path = Util::normalizePath($path);\n        $newpath = Util::normalizePath($newpath);\n        $this->assertPresent($path);\n        $this->assertAbsent($newpath);\n\n        return (bool) $this->getAdapter()->rename($path, $newpath);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function copy($path, $newpath)\n    {\n        $path = Util::normalizePath($path);\n        $newpath = Util::normalizePath($newpath);\n        $this->assertPresent($path);\n        $this->assertAbsent($newpath);\n\n        return $this->getAdapter()->copy($path, $newpath);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function delete($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        return $this->getAdapter()->delete($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function deleteDir($dirname)\n    {\n        $dirname = Util::normalizePath($dirname);\n\n        if ($dirname === '') {\n            throw new RootViolationException('Root directories can not be deleted.');\n        }\n\n        return (bool) $this->getAdapter()->deleteDir($dirname);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function createDir($dirname, array $config = [])\n    {\n        $dirname = Util::normalizePath($dirname);\n        $config = $this->prepareConfig($config);\n\n        return (bool) $this->getAdapter()->createDir($dirname, $config);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function listContents($directory = '', $recursive = false)\n    {\n        $directory = Util::normalizePath($directory);\n        $contents = $this->getAdapter()->listContents($directory, $recursive);\n\n        return (new ContentListingFormatter($directory, $recursive, $this->config->get('case_sensitive', true)))\n            ->formatListing($contents);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMimetype($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        if (( ! $object = $this->getAdapter()->getMimetype($path)) || ! array_key_exists('mimetype', $object)) {\n            return false;\n        }\n\n        return $object['mimetype'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getTimestamp($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        if (( ! $object = $this->getAdapter()->getTimestamp($path)) || ! array_key_exists('timestamp', $object)) {\n            return false;\n        }\n\n        return (int) $object['timestamp'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getVisibility($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        if (( ! $object = $this->getAdapter()->getVisibility($path)) || ! array_key_exists('visibility', $object)) {\n            return false;\n        }\n\n        return $object['visibility'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getSize($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        if (( ! $object = $this->getAdapter()->getSize($path)) || ! array_key_exists('size', $object)) {\n            return false;\n        }\n\n        return (int) $object['size'];\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function setVisibility($path, $visibility)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        return (bool) $this->getAdapter()->setVisibility($path, $visibility);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function getMetadata($path)\n    {\n        $path = Util::normalizePath($path);\n        $this->assertPresent($path);\n\n        return $this->getAdapter()->getMetadata($path);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    public function get($path, Handler $handler = null)\n    {\n        $path = Util::normalizePath($path);\n\n        if ( ! $handler) {\n            $metadata = $this->getMetadata($path);\n            $handler = ($metadata && $metadata['type'] === 'file') ? new File($this, $path) : new Directory($this, $path);\n        }\n\n        $handler->setPath($path);\n        $handler->setFilesystem($this);\n\n        return $handler;\n    }\n\n    /**\n     * Assert a file is present.\n     *\n     * @param string $path path to file\n     *\n     * @throws FileNotFoundException\n     *\n     * @return void\n     */\n    public function assertPresent($path)\n    {\n        if ($this->config->get('disable_asserts', false) === false && ! $this->has($path)) {\n            throw new FileNotFoundException($path);\n        }\n    }\n\n    /**\n     * Assert a file is absent.\n     *\n     * @param string $path path to file\n     *\n     * @throws FileExistsException\n     *\n     * @return void\n     */\n    public function assertAbsent($path)\n    {\n        if ($this->config->get('disable_asserts', false) === false && $this->has($path)) {\n            throw new FileExistsException($path);\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/FilesystemException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\ninterface FilesystemException\n{\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/FilesystemInterface.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse InvalidArgumentException;\n\ninterface FilesystemInterface\n{\n    /**\n     * Check whether a file exists.\n     *\n     * @param string $path\n     *\n     * @return bool\n     */\n    public function has($path);\n\n    /**\n     * Read a file.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The file contents or false on failure.\n     */\n    public function read($path);\n\n    /**\n     * Retrieves a read-stream for a path.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return resource|false The path resource or false on failure.\n     */\n    public function readStream($path);\n\n    /**\n     * List contents of a directory.\n     *\n     * @param string $directory The directory to list.\n     * @param bool   $recursive Whether to list recursively.\n     *\n     * @return array A list of file metadata.\n     */\n    public function listContents($directory = '', $recursive = false);\n\n    /**\n     * Get a file's metadata.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return array|false The file metadata or false on failure.\n     */\n    public function getMetadata($path);\n\n    /**\n     * Get a file's size.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return int|false The file size or false on failure.\n     */\n    public function getSize($path);\n\n    /**\n     * Get a file's mime-type.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The file mime-type or false on failure.\n     */\n    public function getMimetype($path);\n\n    /**\n     * Get a file's timestamp.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return int|false The timestamp or false on failure.\n     */\n    public function getTimestamp($path);\n\n    /**\n     * Get a file's visibility.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The visibility (public|private) or false on failure.\n     */\n    public function getVisibility($path);\n\n    /**\n     * Write a new file.\n     *\n     * @param string $path     The path of the new file.\n     * @param string $contents The file contents.\n     * @param array  $config   An optional configuration array.\n     *\n     * @throws FileExistsException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function write($path, $contents, array $config = []);\n\n    /**\n     * Write a new file using a stream.\n     *\n     * @param string   $path     The path of the new file.\n     * @param resource $resource The file handle.\n     * @param array    $config   An optional configuration array.\n     *\n     * @throws InvalidArgumentException If $resource is not a file handle.\n     * @throws FileExistsException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function writeStream($path, $resource, array $config = []);\n\n    /**\n     * Update an existing file.\n     *\n     * @param string $path     The path of the existing file.\n     * @param string $contents The file contents.\n     * @param array  $config   An optional configuration array.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function update($path, $contents, array $config = []);\n\n    /**\n     * Update an existing file using a stream.\n     *\n     * @param string   $path     The path of the existing file.\n     * @param resource $resource The file handle.\n     * @param array    $config   An optional configuration array.\n     *\n     * @throws InvalidArgumentException If $resource is not a file handle.\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function updateStream($path, $resource, array $config = []);\n\n    /**\n     * Rename a file.\n     *\n     * @param string $path    Path to the existing file.\n     * @param string $newpath The new path of the file.\n     *\n     * @throws FileExistsException   Thrown if $newpath exists.\n     * @throws FileNotFoundException Thrown if $path does not exist.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function rename($path, $newpath);\n\n    /**\n     * Copy a file.\n     *\n     * @param string $path    Path to the existing file.\n     * @param string $newpath The new path of the file.\n     *\n     * @throws FileExistsException   Thrown if $newpath exists.\n     * @throws FileNotFoundException Thrown if $path does not exist.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function copy($path, $newpath);\n\n    /**\n     * Delete a file.\n     *\n     * @param string $path\n     *\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function delete($path);\n\n    /**\n     * Delete a directory.\n     *\n     * @param string $dirname\n     *\n     * @throws RootViolationException Thrown if $dirname is empty.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function deleteDir($dirname);\n\n    /**\n     * Create a directory.\n     *\n     * @param string $dirname The name of the new directory.\n     * @param array  $config  An optional configuration array.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function createDir($dirname, array $config = []);\n\n    /**\n     * Set the visibility for a file.\n     *\n     * @param string $path       The path to the file.\n     * @param string $visibility One of 'public' or 'private'.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function setVisibility($path, $visibility);\n\n    /**\n     * Create a file or update if exists.\n     *\n     * @param string $path     The path to the file.\n     * @param string $contents The file contents.\n     * @param array  $config   An optional configuration array.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function put($path, $contents, array $config = []);\n\n    /**\n     * Create a file or update if exists.\n     *\n     * @param string   $path     The path to the file.\n     * @param resource $resource The file handle.\n     * @param array    $config   An optional configuration array.\n     *\n     * @throws InvalidArgumentException Thrown if $resource is not a resource.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function putStream($path, $resource, array $config = []);\n\n    /**\n     * Read and delete a file.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The file contents, or false on failure.\n     */\n    public function readAndDelete($path);\n\n    /**\n     * Get a file/directory handler.\n     *\n     * @deprecated\n     *\n     * @param string  $path    The path to the file.\n     * @param Handler $handler An optional existing handler to populate.\n     *\n     * @return Handler Either a file or directory handler.\n     */\n    public function get($path, Handler $handler = null);\n\n    /**\n     * Register a plugin.\n     *\n     * @param PluginInterface $plugin The plugin to register.\n     *\n     * @return $this\n     */\n    public function addPlugin(PluginInterface $plugin);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/FilesystemNotFoundException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse LogicException;\n\n/**\n * Thrown when the MountManager cannot find a filesystem.\n */\nclass FilesystemNotFoundException extends LogicException implements FilesystemException\n{\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Handler.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse BadMethodCallException;\n\n/**\n * @deprecated\n */\nabstract class Handler\n{\n    /**\n     * @var string\n     */\n    protected $path;\n\n    /**\n     * @var FilesystemInterface\n     */\n    protected $filesystem;\n\n    /**\n     * Constructor.\n     *\n     * @param FilesystemInterface $filesystem\n     * @param string              $path\n     */\n    public function __construct(FilesystemInterface $filesystem = null, $path = null)\n    {\n        $this->path = $path;\n        $this->filesystem = $filesystem;\n    }\n\n    /**\n     * Check whether the entree is a directory.\n     *\n     * @return bool\n     */\n    public function isDir()\n    {\n        return $this->getType() === 'dir';\n    }\n\n    /**\n     * Check whether the entree is a file.\n     *\n     * @return bool\n     */\n    public function isFile()\n    {\n        return $this->getType() === 'file';\n    }\n\n    /**\n     * Retrieve the entree type (file|dir).\n     *\n     * @return string file or dir\n     */\n    public function getType()\n    {\n        $metadata = $this->filesystem->getMetadata($this->path);\n\n        return $metadata ? $metadata['type'] : 'dir';\n    }\n\n    /**\n     * Set the Filesystem object.\n     *\n     * @param FilesystemInterface $filesystem\n     *\n     * @return $this\n     */\n    public function setFilesystem(FilesystemInterface $filesystem)\n    {\n        $this->filesystem = $filesystem;\n\n        return $this;\n    }\n    \n    /**\n     * Retrieve the Filesystem object.\n     *\n     * @return FilesystemInterface\n     */\n    public function getFilesystem()\n    {\n        return $this->filesystem;\n    }\n\n    /**\n     * Set the entree path.\n     *\n     * @param string $path\n     *\n     * @return $this\n     */\n    public function setPath($path)\n    {\n        $this->path = $path;\n\n        return $this;\n    }\n\n    /**\n     * Retrieve the entree path.\n     *\n     * @return string path\n     */\n    public function getPath()\n    {\n        return $this->path;\n    }\n\n    /**\n     * Plugins pass-through.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return mixed\n     */\n    public function __call($method, array $arguments)\n    {\n        array_unshift($arguments, $this->path);\n        $callback = [$this->filesystem, $method];\n\n        try {\n            return call_user_func_array($callback, $arguments);\n        } catch (BadMethodCallException $e) {\n            throw new BadMethodCallException(\n                'Call to undefined method '\n                . get_called_class()\n                . '::' . $method\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/InvalidRootException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse RuntimeException;\n\nclass InvalidRootException extends RuntimeException implements FilesystemException\n{\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/MountManager.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse InvalidArgumentException;\nuse League\\Flysystem\\Plugin\\PluggableTrait;\nuse League\\Flysystem\\Plugin\\PluginNotFoundException;\n\n/**\n * Class MountManager.\n *\n * Proxies methods to Filesystem (@see __call):\n *\n * @method AdapterInterface getAdapter($prefix)\n * @method Config getConfig($prefix)\n * @method array listFiles($directory = '', $recursive = false)\n * @method array listPaths($directory = '', $recursive = false)\n * @method array getWithMetadata($path, array $metadata)\n * @method Filesystem flushCache()\n * @method void assertPresent($path)\n * @method void assertAbsent($path)\n * @method Filesystem addPlugin(PluginInterface $plugin)\n */\nclass MountManager implements FilesystemInterface\n{\n    use PluggableTrait;\n\n    /**\n     * @var FilesystemInterface[]\n     */\n    protected $filesystems = [];\n\n    /**\n     * Constructor.\n     *\n     * @param FilesystemInterface[] $filesystems [:prefix => Filesystem,]\n     *\n     * @throws InvalidArgumentException\n     */\n    public function __construct(array $filesystems = [])\n    {\n        $this->mountFilesystems($filesystems);\n    }\n\n    /**\n     * Mount filesystems.\n     *\n     * @param FilesystemInterface[] $filesystems [:prefix => Filesystem,]\n     *\n     * @throws InvalidArgumentException\n     *\n     * @return $this\n     */\n    public function mountFilesystems(array $filesystems)\n    {\n        foreach ($filesystems as $prefix => $filesystem) {\n            $this->mountFilesystem($prefix, $filesystem);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Mount filesystems.\n     *\n     * @param string              $prefix\n     * @param FilesystemInterface $filesystem\n     *\n     * @throws InvalidArgumentException\n     *\n     * @return $this\n     */\n    public function mountFilesystem($prefix, FilesystemInterface $filesystem)\n    {\n        if ( ! is_string($prefix)) {\n            throw new InvalidArgumentException(__METHOD__ . ' expects argument #1 to be a string.');\n        }\n\n        $this->filesystems[$prefix] = $filesystem;\n\n        return $this;\n    }\n\n    /**\n     * Get the filesystem with the corresponding prefix.\n     *\n     * @param string $prefix\n     *\n     * @throws FilesystemNotFoundException\n     *\n     * @return FilesystemInterface\n     */\n    public function getFilesystem($prefix)\n    {\n        if ( ! isset($this->filesystems[$prefix])) {\n            throw new FilesystemNotFoundException('No filesystem mounted with prefix ' . $prefix);\n        }\n\n        return $this->filesystems[$prefix];\n    }\n\n    /**\n     * Retrieve the prefix from an arguments array.\n     *\n     * @param array $arguments\n     *\n     * @throws InvalidArgumentException\n     *\n     * @return array [:prefix, :arguments]\n     */\n    public function filterPrefix(array $arguments)\n    {\n        if (empty($arguments)) {\n            throw new InvalidArgumentException('At least one argument needed');\n        }\n\n        $path = array_shift($arguments);\n\n        if ( ! is_string($path)) {\n            throw new InvalidArgumentException('First argument should be a string');\n        }\n\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n        array_unshift($arguments, $path);\n\n        return [$prefix, $arguments];\n    }\n\n    /**\n     * @param string $directory\n     * @param bool   $recursive\n     *\n     * @throws InvalidArgumentException\n     * @throws FilesystemNotFoundException\n     *\n     * @return array\n     */\n    public function listContents($directory = '', $recursive = false)\n    {\n        list($prefix, $directory) = $this->getPrefixAndPath($directory);\n        $filesystem = $this->getFilesystem($prefix);\n        $result = $filesystem->listContents($directory, $recursive);\n\n        foreach ($result as &$file) {\n            $file['filesystem'] = $prefix;\n        }\n\n        return $result;\n    }\n\n    /**\n     * Call forwarder.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @throws InvalidArgumentException\n     * @throws FilesystemNotFoundException\n     *\n     * @return mixed\n     */\n    public function __call($method, $arguments)\n    {\n        list($prefix, $arguments) = $this->filterPrefix($arguments);\n\n        return $this->invokePluginOnFilesystem($method, $arguments, $prefix);\n    }\n\n    /**\n     * @param string $from\n     * @param string $to\n     * @param array  $config\n     *\n     * @throws InvalidArgumentException\n     * @throws FilesystemNotFoundException\n     * @throws FileExistsException\n     *\n     * @return bool\n     */\n    public function copy($from, $to, array $config = [])\n    {\n        list($prefixFrom, $from) = $this->getPrefixAndPath($from);\n\n        $buffer = $this->getFilesystem($prefixFrom)->readStream($from);\n\n        if ($buffer === false) {\n            return false;\n        }\n\n        list($prefixTo, $to) = $this->getPrefixAndPath($to);\n\n        $result = $this->getFilesystem($prefixTo)->writeStream($to, $buffer, $config);\n\n        if (is_resource($buffer)) {\n            fclose($buffer);\n        }\n\n        return $result;\n    }\n\n    /**\n     * List with plugin adapter.\n     *\n     * @param array  $keys\n     * @param string $directory\n     * @param bool   $recursive\n     *\n     * @throws InvalidArgumentException\n     * @throws FilesystemNotFoundException\n     *\n     * @return array\n     */\n    public function listWith(array $keys = [], $directory = '', $recursive = false)\n    {\n        list($prefix, $directory) = $this->getPrefixAndPath($directory);\n        $arguments = [$keys, $directory, $recursive];\n\n        return $this->invokePluginOnFilesystem('listWith', $arguments, $prefix);\n    }\n\n    /**\n     * Move a file.\n     *\n     * @param string $from\n     * @param string $to\n     * @param array  $config\n     *\n     * @throws InvalidArgumentException\n     * @throws FilesystemNotFoundException\n     *\n     * @return bool\n     */\n    public function move($from, $to, array $config = [])\n    {\n        list($prefixFrom, $pathFrom) = $this->getPrefixAndPath($from);\n        list($prefixTo, $pathTo) = $this->getPrefixAndPath($to);\n\n        if ($prefixFrom === $prefixTo) {\n            $filesystem = $this->getFilesystem($prefixFrom);\n            $renamed = $filesystem->rename($pathFrom, $pathTo);\n\n            if ($renamed && isset($config['visibility'])) {\n                return $filesystem->setVisibility($pathTo, $config['visibility']);\n            }\n\n            return $renamed;\n        }\n\n        $copied = $this->copy($from, $to, $config);\n\n        if ($copied) {\n            return $this->delete($from);\n        }\n\n        return false;\n    }\n\n    /**\n     * Invoke a plugin on a filesystem mounted on a given prefix.\n     *\n     * @param string $method\n     * @param array  $arguments\n     * @param string $prefix\n     *\n     * @throws FilesystemNotFoundException\n     *\n     * @return mixed\n     */\n    public function invokePluginOnFilesystem($method, $arguments, $prefix)\n    {\n        $filesystem = $this->getFilesystem($prefix);\n\n        try {\n            return $this->invokePlugin($method, $arguments, $filesystem);\n        } catch (PluginNotFoundException $e) {\n            // Let it pass, it's ok, don't panic.\n        }\n\n        $callback = [$filesystem, $method];\n\n        return call_user_func_array($callback, $arguments);\n    }\n\n    /**\n     * @param string $path\n     *\n     * @throws InvalidArgumentException\n     *\n     * @return string[] [:prefix, :path]\n     */\n    protected function getPrefixAndPath($path)\n    {\n        if (strpos($path, '://') < 1) {\n            throw new InvalidArgumentException('No prefix detected in path: ' . $path);\n        }\n\n        return explode('://', $path, 2);\n    }\n\n    /**\n     * Check whether a file exists.\n     *\n     * @param string $path\n     *\n     * @return bool\n     */\n    public function has($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->has($path);\n    }\n\n    /**\n     * Read a file.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The file contents or false on failure.\n     */\n    public function read($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->read($path);\n    }\n\n    /**\n     * Retrieves a read-stream for a path.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return resource|false The path resource or false on failure.\n     */\n    public function readStream($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->readStream($path);\n    }\n\n    /**\n     * Get a file's metadata.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return array|false The file metadata or false on failure.\n     */\n    public function getMetadata($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->getMetadata($path);\n    }\n\n    /**\n     * Get a file's size.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return int|false The file size or false on failure.\n     */\n    public function getSize($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->getSize($path);\n    }\n\n    /**\n     * Get a file's mime-type.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The file mime-type or false on failure.\n     */\n    public function getMimetype($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->getMimetype($path);\n    }\n\n    /**\n     * Get a file's timestamp.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The timestamp or false on failure.\n     */\n    public function getTimestamp($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->getTimestamp($path);\n    }\n\n    /**\n     * Get a file's visibility.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The visibility (public|private) or false on failure.\n     */\n    public function getVisibility($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->getVisibility($path);\n    }\n\n    /**\n     * Write a new file.\n     *\n     * @param string $path     The path of the new file.\n     * @param string $contents The file contents.\n     * @param array  $config   An optional configuration array.\n     *\n     * @throws FileExistsException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function write($path, $contents, array $config = [])\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->write($path, $contents, $config);\n    }\n\n    /**\n     * Write a new file using a stream.\n     *\n     * @param string   $path     The path of the new file.\n     * @param resource $resource The file handle.\n     * @param array    $config   An optional configuration array.\n     *\n     * @throws InvalidArgumentException If $resource is not a file handle.\n     * @throws FileExistsException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function writeStream($path, $resource, array $config = [])\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->writeStream($path, $resource, $config);\n    }\n\n    /**\n     * Update an existing file.\n     *\n     * @param string $path     The path of the existing file.\n     * @param string $contents The file contents.\n     * @param array  $config   An optional configuration array.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function update($path, $contents, array $config = [])\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->update($path, $contents, $config);\n    }\n\n    /**\n     * Update an existing file using a stream.\n     *\n     * @param string   $path     The path of the existing file.\n     * @param resource $resource The file handle.\n     * @param array    $config   An optional configuration array.\n     *\n     * @throws InvalidArgumentException If $resource is not a file handle.\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function updateStream($path, $resource, array $config = [])\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->updateStream($path, $resource, $config);\n    }\n\n    /**\n     * Rename a file.\n     *\n     * @param string $path    Path to the existing file.\n     * @param string $newpath The new path of the file.\n     *\n     * @throws FileExistsException   Thrown if $newpath exists.\n     * @throws FileNotFoundException Thrown if $path does not exist.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function rename($path, $newpath)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->rename($path, $newpath);\n    }\n\n    /**\n     * Delete a file.\n     *\n     * @param string $path\n     *\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function delete($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->delete($path);\n    }\n\n    /**\n     * Delete a directory.\n     *\n     * @param string $dirname\n     *\n     * @throws RootViolationException Thrown if $dirname is empty.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function deleteDir($dirname)\n    {\n        list($prefix, $dirname) = $this->getPrefixAndPath($dirname);\n\n        return $this->getFilesystem($prefix)->deleteDir($dirname);\n    }\n\n    /**\n     * Create a directory.\n     *\n     * @param string $dirname The name of the new directory.\n     * @param array  $config  An optional configuration array.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function createDir($dirname, array $config = [])\n    {\n        list($prefix, $dirname) = $this->getPrefixAndPath($dirname);\n\n        return $this->getFilesystem($prefix)->createDir($dirname);\n    }\n\n    /**\n     * Set the visibility for a file.\n     *\n     * @param string $path       The path to the file.\n     * @param string $visibility One of 'public' or 'private'.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function setVisibility($path, $visibility)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->setVisibility($path, $visibility);\n    }\n\n    /**\n     * Create a file or update if exists.\n     *\n     * @param string $path     The path to the file.\n     * @param string $contents The file contents.\n     * @param array  $config   An optional configuration array.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function put($path, $contents, array $config = [])\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->put($path, $contents, $config);\n    }\n\n    /**\n     * Create a file or update if exists.\n     *\n     * @param string   $path     The path to the file.\n     * @param resource $resource The file handle.\n     * @param array    $config   An optional configuration array.\n     *\n     * @throws InvalidArgumentException Thrown if $resource is not a resource.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function putStream($path, $resource, array $config = [])\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->putStream($path, $resource, $config);\n    }\n\n    /**\n     * Read and delete a file.\n     *\n     * @param string $path The path to the file.\n     *\n     * @throws FileNotFoundException\n     *\n     * @return string|false The file contents, or false on failure.\n     */\n    public function readAndDelete($path)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->readAndDelete($path);\n    }\n\n    /**\n     * Get a file/directory handler.\n     *\n     * @deprecated\n     *\n     * @param string  $path    The path to the file.\n     * @param Handler $handler An optional existing handler to populate.\n     *\n     * @return Handler Either a file or directory handler.\n     */\n    public function get($path, Handler $handler = null)\n    {\n        list($prefix, $path) = $this->getPrefixAndPath($path);\n\n        return $this->getFilesystem($prefix)->get($path);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/NotSupportedException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse RuntimeException;\nuse SplFileInfo;\n\nclass NotSupportedException extends RuntimeException implements FilesystemException\n{\n    /**\n     * Create a new exception for a link.\n     *\n     * @param SplFileInfo $file\n     *\n     * @return static\n     */\n    public static function forLink(SplFileInfo $file)\n    {\n        $message = 'Links are not supported, encountered link at ';\n\n        return new static($message . $file->getPathname());\n    }\n\n    /**\n     * Create a new exception for a link.\n     *\n     * @param string $systemType\n     *\n     * @return static\n     */\n    public static function forFtpSystemType($systemType)\n    {\n        $message = \"The FTP system type '$systemType' is currently not supported.\";\n\n        return new static($message);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/AbstractPlugin.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nuse League\\Flysystem\\FilesystemInterface;\nuse League\\Flysystem\\PluginInterface;\n\nabstract class AbstractPlugin implements PluginInterface\n{\n    /**\n     * @var FilesystemInterface\n     */\n    protected $filesystem;\n\n    /**\n     * Set the Filesystem object.\n     *\n     * @param FilesystemInterface $filesystem\n     */\n    public function setFilesystem(FilesystemInterface $filesystem)\n    {\n        $this->filesystem = $filesystem;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/EmptyDir.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nclass EmptyDir extends AbstractPlugin\n{\n    /**\n     * Get the method name.\n     *\n     * @return string\n     */\n    public function getMethod()\n    {\n        return 'emptyDir';\n    }\n\n    /**\n     * Empty a directory's contents.\n     *\n     * @param string $dirname\n     */\n    public function handle($dirname)\n    {\n        $listing = $this->filesystem->listContents($dirname, false);\n\n        foreach ($listing as $item) {\n            if ($item['type'] === 'dir') {\n                $this->filesystem->deleteDir($item['path']);\n            } else {\n                $this->filesystem->delete($item['path']);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/ForcedCopy.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nuse League\\Flysystem\\FileExistsException;\nuse League\\Flysystem\\FileNotFoundException;\n\nclass ForcedCopy extends AbstractPlugin\n{\n    /**\n     * @inheritdoc\n     */\n    public function getMethod()\n    {\n        return 'forceCopy';\n    }\n\n    /**\n     * Copies a file, overwriting any existing files.\n     *\n     * @param string $path    Path to the existing file.\n     * @param string $newpath The new path of the file.\n     *\n     * @throws FileExistsException\n     * @throws FileNotFoundException Thrown if $path does not exist.\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function handle($path, $newpath)\n    {\n        try {\n            $deleted = $this->filesystem->delete($newpath);\n        } catch (FileNotFoundException $e) {\n            // The destination path does not exist. That's ok.\n            $deleted = true;\n        }\n\n        if ($deleted) {\n            return $this->filesystem->copy($path, $newpath);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/ForcedRename.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nuse League\\Flysystem\\FileExistsException;\nuse League\\Flysystem\\FileNotFoundException;\n\nclass ForcedRename extends AbstractPlugin\n{\n    /**\n     * @inheritdoc\n     */\n    public function getMethod()\n    {\n        return 'forceRename';\n    }\n\n    /**\n     * Renames a file, overwriting the destination if it exists.\n     *\n     * @param string $path    Path to the existing file.\n     * @param string $newpath The new path of the file.\n     *\n     * @throws FileNotFoundException Thrown if $path does not exist.\n     * @throws FileExistsException\n     *\n     * @return bool True on success, false on failure.\n     */\n    public function handle($path, $newpath)\n    {\n        try {\n            $deleted = $this->filesystem->delete($newpath);\n        } catch (FileNotFoundException $e) {\n            // The destination path does not exist. That's ok.\n            $deleted = true;\n        }\n\n        if ($deleted) {\n            return $this->filesystem->rename($path, $newpath);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/GetWithMetadata.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nuse InvalidArgumentException;\nuse League\\Flysystem\\FileNotFoundException;\n\nclass GetWithMetadata extends AbstractPlugin\n{\n    /**\n     * Get the method name.\n     *\n     * @return string\n     */\n    public function getMethod()\n    {\n        return 'getWithMetadata';\n    }\n\n    /**\n     * Get metadata for an object with required metadata.\n     *\n     * @param string   $path     path to file\n     * @param string[] $metadata metadata keys\n     *\n     * @throws InvalidArgumentException\n     * @throws FileNotFoundException\n     *\n     * @return array|false metadata\n     */\n    public function handle($path, array $metadata)\n    {\n        $object = $this->filesystem->getMetadata($path);\n\n        if ( ! $object) {\n            return false;\n        }\n\n        $keys = array_diff($metadata, array_keys($object));\n\n        foreach ($keys as $key) {\n            if ( ! method_exists($this->filesystem, $method = 'get' . ucfirst($key))) {\n                throw new InvalidArgumentException('Could not fetch metadata: ' . $key);\n            }\n\n            $object[$key] = $this->filesystem->{$method}($path);\n        }\n\n        return $object;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/ListFiles.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nclass ListFiles extends AbstractPlugin\n{\n    /**\n     * Get the method name.\n     *\n     * @return string\n     */\n    public function getMethod()\n    {\n        return 'listFiles';\n    }\n\n    /**\n     * List all files in the directory.\n     *\n     * @param string $directory\n     * @param bool   $recursive\n     *\n     * @return array\n     */\n    public function handle($directory = '', $recursive = false)\n    {\n        $contents = $this->filesystem->listContents($directory, $recursive);\n\n        $filter = function ($object) {\n            return $object['type'] === 'file';\n        };\n\n        return array_values(array_filter($contents, $filter));\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/ListPaths.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nclass ListPaths extends AbstractPlugin\n{\n    /**\n     * Get the method name.\n     *\n     * @return string\n     */\n    public function getMethod()\n    {\n        return 'listPaths';\n    }\n\n    /**\n     * List all paths.\n     *\n     * @param string $directory\n     * @param bool   $recursive\n     *\n     * @return string[] paths\n     */\n    public function handle($directory = '', $recursive = false)\n    {\n        $result = [];\n        $contents = $this->filesystem->listContents($directory, $recursive);\n\n        foreach ($contents as $object) {\n            $result[] = $object['path'];\n        }\n\n        return $result;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/ListWith.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nclass ListWith extends AbstractPlugin\n{\n    /**\n     * Get the method name.\n     *\n     * @return string\n     */\n    public function getMethod()\n    {\n        return 'listWith';\n    }\n\n    /**\n     * List contents with metadata.\n     *\n     * @param string[] $keys\n     * @param string   $directory\n     * @param bool     $recursive\n     *\n     * @return array listing with metadata\n     */\n    public function handle(array $keys = [], $directory = '', $recursive = false)\n    {\n        $contents = $this->filesystem->listContents($directory, $recursive);\n\n        foreach ($contents as $index => $object) {\n            if ($object['type'] === 'file') {\n                $missingKeys = array_diff($keys, array_keys($object));\n                $contents[$index] = array_reduce($missingKeys, [$this, 'getMetadataByName'], $object);\n            }\n        }\n\n        return $contents;\n    }\n\n    /**\n     * Get a meta-data value by key name.\n     *\n     * @param array  $object\n     * @param string $key\n     *\n     * @return array\n     */\n    protected function getMetadataByName(array $object, $key)\n    {\n        $method = 'get' . ucfirst($key);\n\n        if ( ! method_exists($this->filesystem, $method)) {\n            throw new \\InvalidArgumentException('Could not get meta-data for key: ' . $key);\n        }\n\n        $object[$key] = $this->filesystem->{$method}($object['path']);\n\n        return $object;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/PluggableTrait.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nuse BadMethodCallException;\nuse League\\Flysystem\\FilesystemInterface;\nuse League\\Flysystem\\PluginInterface;\nuse LogicException;\n\ntrait PluggableTrait\n{\n    /**\n     * @var array\n     */\n    protected $plugins = [];\n\n    /**\n     * Register a plugin.\n     *\n     * @param PluginInterface $plugin\n     *\n     * @throws LogicException\n     *\n     * @return $this\n     */\n    public function addPlugin(PluginInterface $plugin)\n    {\n        if ( ! method_exists($plugin, 'handle')) {\n            throw new LogicException(get_class($plugin) . ' does not have a handle method.');\n        }\n\n        $this->plugins[$plugin->getMethod()] = $plugin;\n\n        return $this;\n    }\n\n    /**\n     * Find a specific plugin.\n     *\n     * @param string $method\n     *\n     * @throws PluginNotFoundException\n     *\n     * @return PluginInterface\n     */\n    protected function findPlugin($method)\n    {\n        if ( ! isset($this->plugins[$method])) {\n            throw new PluginNotFoundException('Plugin not found for method: ' . $method);\n        }\n\n        return $this->plugins[$method];\n    }\n\n    /**\n     * Invoke a plugin by method name.\n     *\n     * @param string              $method\n     * @param array               $arguments\n     * @param FilesystemInterface $filesystem\n     *\n     * @throws PluginNotFoundException\n     *\n     * @return mixed\n     */\n    protected function invokePlugin($method, array $arguments, FilesystemInterface $filesystem)\n    {\n        $plugin = $this->findPlugin($method);\n        $plugin->setFilesystem($filesystem);\n        $callback = [$plugin, 'handle'];\n\n        return call_user_func_array($callback, $arguments);\n    }\n\n    /**\n     * Plugins pass-through.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @throws BadMethodCallException\n     *\n     * @return mixed\n     */\n    public function __call($method, array $arguments)\n    {\n        try {\n            return $this->invokePlugin($method, $arguments, $this);\n        } catch (PluginNotFoundException $e) {\n            throw new BadMethodCallException(\n                'Call to undefined method '\n                . get_class($this)\n                . '::' . $method\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Plugin/PluginNotFoundException.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Plugin;\n\nuse LogicException;\n\nclass PluginNotFoundException extends LogicException\n{\n    // This exception doesn't require additional information.\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/PluginInterface.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\ninterface PluginInterface\n{\n    /**\n     * Get the method name.\n     *\n     * @return string\n     */\n    public function getMethod();\n\n    /**\n     * Set the Filesystem object.\n     *\n     * @param FilesystemInterface $filesystem\n     */\n    public function setFilesystem(FilesystemInterface $filesystem);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/ReadInterface.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\ninterface ReadInterface\n{\n    /**\n     * Check whether a file exists.\n     *\n     * @param string $path\n     *\n     * @return array|bool|null\n     */\n    public function has($path);\n\n    /**\n     * Read a file.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function read($path);\n\n    /**\n     * Read a file as a stream.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function readStream($path);\n\n    /**\n     * List contents of a directory.\n     *\n     * @param string $directory\n     * @param bool   $recursive\n     *\n     * @return array\n     */\n    public function listContents($directory = '', $recursive = false);\n\n    /**\n     * Get all the meta data of a file or directory.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function getMetadata($path);\n\n    /**\n     * Get the size of a file.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function getSize($path);\n\n    /**\n     * Get the mimetype of a file.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function getMimetype($path);\n\n    /**\n     * Get the last modified time of a file as a timestamp.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function getTimestamp($path);\n\n    /**\n     * Get the visibility of a file.\n     *\n     * @param string $path\n     *\n     * @return array|false\n     */\n    public function getVisibility($path);\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/RootViolationException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse LogicException;\n\nclass RootViolationException extends LogicException implements FilesystemException\n{\n    //\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/SafeStorage.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nfinal class SafeStorage\n{\n    /**\n     * @var string\n     */\n    private $hash;\n\n    /**\n     * @var array\n     */\n    protected static $safeStorage = [];\n\n    public function __construct()\n    {\n        $this->hash = spl_object_hash($this);\n        static::$safeStorage[$this->hash] = [];\n    }\n\n    public function storeSafely($key, $value)\n    {\n        static::$safeStorage[$this->hash][$key] = $value;\n    }\n\n    public function retrieveSafely($key)\n    {\n        if (array_key_exists($key, static::$safeStorage[$this->hash])) {\n            return static::$safeStorage[$this->hash][$key];\n        }\n    }\n\n    public function __destruct()\n    {\n        unset(static::$safeStorage[$this->hash]);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/UnreadableFileException.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse SplFileInfo;\n\nclass UnreadableFileException extends Exception\n{\n    public static function forFileInfo(SplFileInfo $fileInfo)\n    {\n        return new static(\n            sprintf(\n                'Unreadable file encountered: %s',\n                $fileInfo->getRealPath()\n            )\n        );\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Util/ContentListingFormatter.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Util;\n\nuse League\\Flysystem\\Util;\n\n/**\n * @internal\n */\nclass ContentListingFormatter\n{\n    /**\n     * @var string\n     */\n    private $directory;\n\n    /**\n     * @var bool\n     */\n    private $recursive;\n\n    /**\n     * @var bool\n     */\n    private $caseSensitive;\n\n    /**\n     * @param string $directory\n     * @param bool   $recursive\n     */\n    public function __construct($directory, $recursive, $caseSensitive = true)\n    {\n        $this->directory = rtrim($directory, '/');\n        $this->recursive = $recursive;\n        $this->caseSensitive = $caseSensitive;\n    }\n\n    /**\n     * Format contents listing.\n     *\n     * @param array $listing\n     *\n     * @return array\n     */\n    public function formatListing(array $listing)\n    {\n        $listing = array_filter(array_map([$this, 'addPathInfo'], $listing), [$this, 'isEntryOutOfScope']);\n\n        return $this->sortListing(array_values($listing));\n    }\n\n    private function addPathInfo(array $entry)\n    {\n        return $entry + Util::pathinfo($entry['path']);\n    }\n\n    /**\n     * Determine if the entry is out of scope.\n     *\n     * @param array $entry\n     *\n     * @return bool\n     */\n    private function isEntryOutOfScope(array $entry)\n    {\n        if (empty($entry['path']) && $entry['path'] !== '0') {\n            return false;\n        }\n\n        if ($this->recursive) {\n            return $this->residesInDirectory($entry);\n        }\n\n        return $this->isDirectChild($entry);\n    }\n\n    /**\n     * Check if the entry resides within the parent directory.\n     *\n     * @param array $entry\n     *\n     * @return bool\n     */\n    private function residesInDirectory(array $entry)\n    {\n        if ($this->directory === '') {\n            return true;\n        }\n\n        return $this->caseSensitive\n            ? strpos($entry['path'], $this->directory . '/') === 0\n            : stripos($entry['path'], $this->directory . '/') === 0;\n    }\n\n    /**\n     * Check if the entry is a direct child of the directory.\n     *\n     * @param array $entry\n     *\n     * @return bool\n     */\n    private function isDirectChild(array $entry)\n    {\n        return $this->caseSensitive\n            ? $entry['dirname'] === $this->directory\n            : strcasecmp($this->directory, $entry['dirname']) === 0;\n    }\n\n    /**\n     * @param array $listing\n     *\n     * @return array\n     */\n    private function sortListing(array $listing)\n    {\n        usort($listing, function ($a, $b) {\n            return strcasecmp($a['path'], $b['path']);\n        });\n\n        return $listing;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Util/MimeType.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Util;\n\nuse League\\MimeTypeDetection\\FinfoMimeTypeDetector;\nuse League\\MimeTypeDetection\\GeneratedExtensionToMimeTypeMap;\nuse League\\MimeTypeDetection\\MimeTypeDetector;\n\n/**\n * @internal\n */\nclass MimeType\n{\n    protected static $extensionToMimeTypeMap = GeneratedExtensionToMimeTypeMap::MIME_TYPES_FOR_EXTENSIONS;\n    protected static $detector;\n\n    public static function useDetector(MimeTypeDetector $detector)\n    {\n        static::$detector = $detector;\n    }\n\n    /**\n     * @return MimeTypeDetector\n     */\n    protected static function detector()\n    {\n        if ( ! static::$detector instanceof MimeTypeDetector) {\n            static::$detector = new FinfoMimeTypeDetector();\n        }\n\n        return static::$detector;\n    }\n\n\n    /**\n     * Detects MIME Type based on given content.\n     *\n     * @param mixed $content\n     *\n     * @return string MIME Type\n     */\n    public static function detectByContent($content)\n    {\n        if (is_string($content)) {\n            return static::detector()->detectMimeTypeFromBuffer($content);\n        }\n\n        return 'text/plain';\n    }\n\n    /**\n     * Detects MIME Type based on file extension.\n     *\n     * @param string $extension\n     *\n     * @return string MIME Type\n     */\n    public static function detectByFileExtension($extension)\n    {\n        return static::detector()->detectMimeTypeFromPath('artificial.' . $extension) ?: 'text/plain';\n    }\n\n    /**\n     * @param string $filename\n     *\n     * @return string MIME Type\n     */\n    public static function detectByFilename($filename)\n    {\n        return static::detector()->detectMimeTypeFromPath($filename) ?: 'text/plain';\n    }\n\n    /**\n     * @return array Map of file extension to MIME Type\n     */\n    public static function getExtensionToMimeTypeMap()\n    {\n        return static::$extensionToMimeTypeMap;\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Util/StreamHasher.php",
    "content": "<?php\n\nnamespace League\\Flysystem\\Util;\n\nclass StreamHasher\n{\n    /**\n     * @var string\n     */\n    private $algo;\n\n    /**\n     * StreamHasher constructor.\n     *\n     * @param string $algo\n     */\n    public function __construct($algo)\n    {\n        $this->algo = $algo;\n    }\n\n    /**\n     * @param resource $resource\n     *\n     * @return string\n     */\n    public function hash($resource)\n    {\n        rewind($resource);\n        $context = hash_init($this->algo);\n        hash_update_stream($context, $resource);\n        fclose($resource);\n\n        return hash_final($context);\n    }\n}\n"
  },
  {
    "path": "vendor/league/flysystem/src/Util.php",
    "content": "<?php\n\nnamespace League\\Flysystem;\n\nuse League\\Flysystem\\Util\\MimeType;\nuse LogicException;\n\nuse function strcmp;\n\nclass Util\n{\n    /**\n     * Get normalized pathinfo.\n     *\n     * @param string $path\n     *\n     * @return array pathinfo\n     */\n    public static function pathinfo($path)\n    {\n        $pathinfo = compact('path');\n\n        if ('' !== $dirname = dirname($path)) {\n            $pathinfo['dirname'] = static::normalizeDirname($dirname);\n        }\n\n        $pathinfo['basename'] = static::basename($path);\n\n        $pathinfo += pathinfo($pathinfo['basename']);\n\n        return $pathinfo + ['dirname' => ''];\n    }\n\n    /**\n     * Normalize a dirname return value.\n     *\n     * @param string $dirname\n     *\n     * @return string normalized dirname\n     */\n    public static function normalizeDirname($dirname)\n    {\n        return $dirname === '.' ? '' : $dirname;\n    }\n\n    /**\n     * Get a normalized dirname from a path.\n     *\n     * @param string $path\n     *\n     * @return string dirname\n     */\n    public static function dirname($path)\n    {\n        return static::normalizeDirname(dirname($path));\n    }\n\n    /**\n     * Map result arrays.\n     *\n     * @param array $object\n     * @param array $map\n     *\n     * @return array mapped result\n     */\n    public static function map(array $object, array $map)\n    {\n        $result = [];\n\n        foreach ($map as $from => $to) {\n            if ( ! isset($object[$from])) {\n                continue;\n            }\n\n            $result[$to] = $object[$from];\n        }\n\n        return $result;\n    }\n\n    /**\n     * Normalize path.\n     *\n     * @param string $path\n     *\n     * @throws LogicException\n     *\n     * @return string\n     */\n    public static function normalizePath($path)\n    {\n        return static::normalizeRelativePath($path);\n    }\n\n    /**\n     * Normalize relative directories in a path.\n     *\n     * @param string $path\n     *\n     * @throws LogicException\n     *\n     * @return string\n     */\n    public static function normalizeRelativePath($path)\n    {\n        $path = str_replace('\\\\', '/', $path);\n        $path =  static::removeFunkyWhiteSpace($path);\n        $parts = [];\n\n        foreach (explode('/', $path) as $part) {\n            switch ($part) {\n                case '':\n                case '.':\n                break;\n\n            case '..':\n                if (empty($parts)) {\n                    throw new LogicException(\n                        'Path is outside of the defined root, path: [' . $path . ']'\n                    );\n                }\n                array_pop($parts);\n                break;\n\n            default:\n                $parts[] = $part;\n                break;\n            }\n        }\n\n        $path = implode('/', $parts);\n\n        return $path;\n    }\n\n    /**\n     * Rejects unprintable characters and invalid unicode characters.\n     *\n     * @param string $path\n     *\n     * @return string $path\n     */\n    protected static function removeFunkyWhiteSpace($path)\n    {\n        if (preg_match('#\\p{C}+#u', $path)) {\n            throw CorruptedPathDetected::forPath($path);\n        }\n\n        return $path;\n    }\n\n    /**\n     * Normalize prefix.\n     *\n     * @param string $prefix\n     * @param string $separator\n     *\n     * @return string normalized path\n     */\n    public static function normalizePrefix($prefix, $separator)\n    {\n        return rtrim($prefix, $separator) . $separator;\n    }\n\n    /**\n     * Get content size.\n     *\n     * @param string $contents\n     *\n     * @return int content size\n     */\n    public static function contentSize($contents)\n    {\n        return defined('MB_OVERLOAD_STRING') ? mb_strlen($contents, '8bit') : strlen($contents);\n    }\n\n    /**\n     * Guess MIME Type based on the path of the file and it's content.\n     *\n     * @param string          $path\n     * @param string|resource $content\n     *\n     * @return string|null MIME Type or NULL if no extension detected\n     */\n    public static function guessMimeType($path, $content)\n    {\n        $mimeType = MimeType::detectByContent($content);\n\n        if ( ! (empty($mimeType) || in_array($mimeType, ['application/x-empty', 'text/plain', 'text/x-asm']))) {\n            return $mimeType;\n        }\n\n        return MimeType::detectByFilename($path);\n    }\n\n    /**\n     * Emulate directories.\n     *\n     * @param array $listing\n     *\n     * @return array listing with emulated directories\n     */\n    public static function emulateDirectories(array $listing)\n    {\n        $directories = [];\n        $listedDirectories = [];\n\n        foreach ($listing as $object) {\n            [$directories, $listedDirectories] = static::emulateObjectDirectories($object, $directories, $listedDirectories);\n        }\n\n        $directories = array_diff(array_unique($directories), array_unique($listedDirectories));\n\n        foreach ($directories as $directory) {\n            $listing[] = static::pathinfo($directory) + ['type' => 'dir'];\n        }\n\n        return $listing;\n    }\n\n    /**\n     * Ensure a Config instance.\n     *\n     * @param null|array|Config $config\n     *\n     * @return Config config instance\n     *\n     * @throw  LogicException\n     */\n    public static function ensureConfig($config)\n    {\n        if ($config === null) {\n            return new Config();\n        }\n\n        if ($config instanceof Config) {\n            return $config;\n        }\n\n        if (is_array($config)) {\n            return new Config($config);\n        }\n\n        throw new LogicException('A config should either be an array or a Flysystem\\Config object.');\n    }\n\n    /**\n     * Rewind a stream.\n     *\n     * @param resource $resource\n     */\n    public static function rewindStream($resource)\n    {\n        if (ftell($resource) !== 0 && static::isSeekableStream($resource)) {\n            rewind($resource);\n        }\n    }\n\n    public static function isSeekableStream($resource)\n    {\n        $metadata = stream_get_meta_data($resource);\n\n        return $metadata['seekable'];\n    }\n\n    /**\n     * Get the size of a stream.\n     *\n     * @param resource $resource\n     *\n     * @return int|null stream size\n     */\n    public static function getStreamSize($resource)\n    {\n        $stat = fstat($resource);\n\n        if ( ! is_array($stat) || ! isset($stat['size'])) {\n            return null;\n        }\n\n        return $stat['size'];\n    }\n\n    /**\n     * Emulate the directories of a single object.\n     *\n     * @param array $object\n     * @param array $directories\n     * @param array $listedDirectories\n     *\n     * @return array\n     */\n    protected static function emulateObjectDirectories(array $object, array $directories, array $listedDirectories)\n    {\n        if ($object['type'] === 'dir') {\n            $listedDirectories[] = $object['path'];\n        }\n\n        if ( ! isset($object['dirname']) || trim($object['dirname']) === '') {\n            return [$directories, $listedDirectories];\n        }\n\n        $parent = $object['dirname'];\n\n        while (isset($parent) && trim($parent) !== '' && ! in_array($parent, $directories)) {\n            $directories[] = $parent;\n            $parent = static::dirname($parent);\n        }\n\n        if (isset($object['type']) && $object['type'] === 'dir') {\n            $listedDirectories[] = $object['path'];\n\n            return [$directories, $listedDirectories];\n        }\n\n        return [$directories, $listedDirectories];\n    }\n\n    /**\n     * Returns the trailing name component of the path.\n     *\n     * @param string $path\n     *\n     * @return string\n     */\n    private static function basename($path)\n    {\n        $separators = DIRECTORY_SEPARATOR === '/' ? '/' : '\\/';\n\n        $path = rtrim($path, $separators);\n\n        $basename = preg_replace('#.*?([^' . preg_quote($separators, '#') . ']+$)#', '$1', $path);\n\n        if (DIRECTORY_SEPARATOR === '/') {\n            return $basename;\n        }\n        // @codeCoverageIgnoreStart\n        // Extra Windows path munging. This is tested via AppVeyor, but code\n        // coverage is not reported.\n\n        // Handle relative paths with drive letters. c:file.txt.\n        while (preg_match('#^[a-zA-Z]{1}:[^\\\\\\/]#', $basename)) {\n            $basename = substr($basename, 2);\n        }\n\n        // Remove colon for standalone drive letter names.\n        if (preg_match('#^[a-zA-Z]{1}:$#', $basename)) {\n            $basename = rtrim($basename, ':');\n        }\n\n        return $basename;\n        // @codeCoverageIgnoreEnd\n    }\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/CHANGELOG.md",
    "content": "# Changelog\n\n## 1.10.0 - 2022-04-11\n\n### Fixed\n\n- Added Flysystem v1 inconclusive mime-types and made it configurable as a constructor parameter.\n\n## 1.9.0 - 2021-11-21\n\n### Updated\n\n- Updated lookup\n\n## 1.8.0 - 2021-09-25\n\n### Added\n\n- Added the decorator `OverridingExtensionToMimeTypeMap` which allows you to override values.\n\n## 1.7.0 - 2021-01-18\n\n### Added\n\n- Added a `bufferSampleSize` parameter to the `FinfoMimeTypeDetector` class that allows you to send a reduced content sample which costs less memory.\n\n## 1.6.0 - 2021-01-18\n\n### Changes\n\n- Updated generated mime-type map\n"
  },
  {
    "path": "vendor/league/mime-type-detection/LICENSE",
    "content": "Copyright (c) 2013-2022 Frank de Jonge\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/league/mime-type-detection/composer.json",
    "content": "{\n    \"name\": \"league/mime-type-detection\",\n    \"description\": \"Mime-type detection for Flysystem\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Frank de Jonge\",\n            \"email\": \"info@frankdejonge.nl\"\n        }\n    ],\n    \"scripts\": {\n        \"test\": \"vendor/bin/phpunit\",\n        \"phpstan\": \"vendor/bin/phpstan analyse -l 6 src\"\n    },\n    \"require\": {\n        \"php\": \"^7.2 || ^8.0\",\n        \"ext-fileinfo\": \"*\"\n    },\n    \"require-dev\": {\n        \"phpunit/phpunit\": \"^8.5.8 || ^9.3\",\n        \"phpstan/phpstan\": \"^0.12.68\",\n        \"friendsofphp/php-cs-fixer\": \"^3.2\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"League\\\\MimeTypeDetection\\\\\": \"src\"\n        }\n    },\n    \"config\": {\n        \"platform\": {\n            \"php\": \"7.2.0\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/EmptyExtensionToMimeTypeMap.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\MimeTypeDetection;\n\nclass EmptyExtensionToMimeTypeMap implements ExtensionToMimeTypeMap\n{\n    public function lookupMimeType(string $extension): ?string\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\MimeTypeDetection;\n\nuse const PATHINFO_EXTENSION;\n\nclass ExtensionMimeTypeDetector implements MimeTypeDetector\n{\n    /**\n     * @var ExtensionToMimeTypeMap\n     */\n    private $extensions;\n\n    public function __construct(ExtensionToMimeTypeMap $extensions = null)\n    {\n        $this->extensions = $extensions ?: new GeneratedExtensionToMimeTypeMap();\n    }\n\n    public function detectMimeType(string $path, $contents): ?string\n    {\n        return $this->detectMimeTypeFromPath($path);\n    }\n\n    public function detectMimeTypeFromPath(string $path): ?string\n    {\n        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));\n\n        return $this->extensions->lookupMimeType($extension);\n    }\n\n    public function detectMimeTypeFromFile(string $path): ?string\n    {\n        return $this->detectMimeTypeFromPath($path);\n    }\n\n    public function detectMimeTypeFromBuffer(string $contents): ?string\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/ExtensionToMimeTypeMap.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\MimeTypeDetection;\n\ninterface ExtensionToMimeTypeMap\n{\n    public function lookupMimeType(string $extension): ?string;\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\MimeTypeDetection;\n\nuse const FILEINFO_MIME_TYPE;\n\nuse const PATHINFO_EXTENSION;\nuse finfo;\n\nclass FinfoMimeTypeDetector implements MimeTypeDetector\n{\n    private const INCONCLUSIVE_MIME_TYPES = [\n        'application/x-empty',\n        'text/plain',\n        'text/x-asm',\n        'application/octet-stream',\n        'inode/x-empty',\n    ];\n\n    /**\n     * @var finfo\n     */\n    private $finfo;\n\n    /**\n     * @var ExtensionToMimeTypeMap\n     */\n    private $extensionMap;\n\n    /**\n     * @var int|null\n     */\n    private $bufferSampleSize;\n\n    /**\n     * @var array<string>\n     */\n    private $inconclusiveMimetypes;\n\n    public function __construct(\n        string $magicFile = '',\n        ExtensionToMimeTypeMap $extensionMap = null,\n        ?int $bufferSampleSize = null,\n        array $inconclusiveMimetypes = self::INCONCLUSIVE_MIME_TYPES\n    ) {\n        $this->finfo = new finfo(FILEINFO_MIME_TYPE, $magicFile);\n        $this->extensionMap = $extensionMap ?: new GeneratedExtensionToMimeTypeMap();\n        $this->bufferSampleSize = $bufferSampleSize;\n        $this->inconclusiveMimetypes = $inconclusiveMimetypes;\n    }\n\n    public function detectMimeType(string $path, $contents): ?string\n    {\n        $mimeType = is_string($contents)\n            ? (@$this->finfo->buffer($this->takeSample($contents)) ?: null)\n            : null;\n\n        if ($mimeType !== null && ! in_array($mimeType, $this->inconclusiveMimetypes)) {\n            return $mimeType;\n        }\n\n        return $this->detectMimeTypeFromPath($path);\n    }\n\n    public function detectMimeTypeFromPath(string $path): ?string\n    {\n        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));\n\n        return $this->extensionMap->lookupMimeType($extension);\n    }\n\n    public function detectMimeTypeFromFile(string $path): ?string\n    {\n        return @$this->finfo->file($path) ?: null;\n    }\n\n    public function detectMimeTypeFromBuffer(string $contents): ?string\n    {\n        return @$this->finfo->buffer($this->takeSample($contents)) ?: null;\n    }\n\n    private function takeSample(string $contents): string\n    {\n        if ($this->bufferSampleSize === null) {\n            return $contents;\n        }\n\n        return (string) substr($contents, 0, $this->bufferSampleSize);\n    }\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\MimeTypeDetection;\n\nclass GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap\n{\n    /**\n     * @var string[]\n     *\n     * @internal\n     */\n    public const MIME_TYPES_FOR_EXTENSIONS = [\n        '1km' => 'application/vnd.1000minds.decision-model+xml',\n        '3dml' => 'text/vnd.in3d.3dml',\n        '3ds' => 'image/x-3ds',\n        '3g2' => 'video/3gpp2',\n        '3gp' => 'video/3gp',\n        '3gpp' => 'video/3gpp',\n        '3mf' => 'model/3mf',\n        '7z' => 'application/x-7z-compressed',\n        '7zip' => 'application/x-7z-compressed',\n        '123' => 'application/vnd.lotus-1-2-3',\n        'aab' => 'application/x-authorware-bin',\n        'aac' => 'audio/x-acc',\n        'aam' => 'application/x-authorware-map',\n        'aas' => 'application/x-authorware-seg',\n        'abw' => 'application/x-abiword',\n        'ac' => 'application/vnd.nokia.n-gage.ac+xml',\n        'ac3' => 'audio/ac3',\n        'acc' => 'application/vnd.americandynamics.acc',\n        'ace' => 'application/x-ace-compressed',\n        'acu' => 'application/vnd.acucobol',\n        'acutc' => 'application/vnd.acucorp',\n        'adp' => 'audio/adpcm',\n        'aep' => 'application/vnd.audiograph',\n        'afm' => 'application/x-font-type1',\n        'afp' => 'application/vnd.ibm.modcap',\n        'age' => 'application/vnd.age',\n        'ahead' => 'application/vnd.ahead.space',\n        'ai' => 'application/pdf',\n        'aif' => 'audio/x-aiff',\n        'aifc' => 'audio/x-aiff',\n        'aiff' => 'audio/x-aiff',\n        'air' => 'application/vnd.adobe.air-application-installer-package+zip',\n        'ait' => 'application/vnd.dvb.ait',\n        'ami' => 'application/vnd.amiga.ami',\n        'amr' => 'audio/amr',\n        'apk' => 'application/vnd.android.package-archive',\n        'apng' => 'image/apng',\n        'appcache' => 'text/cache-manifest',\n        'application' => 'application/x-ms-application',\n        'apr' => 'application/vnd.lotus-approach',\n        'arc' => 'application/x-freearc',\n        'arj' => 'application/x-arj',\n        'asc' => 'application/pgp-signature',\n        'asf' => 'video/x-ms-asf',\n        'asm' => 'text/x-asm',\n        'aso' => 'application/vnd.accpac.simply.aso',\n        'asx' => 'video/x-ms-asf',\n        'atc' => 'application/vnd.acucorp',\n        'atom' => 'application/atom+xml',\n        'atomcat' => 'application/atomcat+xml',\n        'atomdeleted' => 'application/atomdeleted+xml',\n        'atomsvc' => 'application/atomsvc+xml',\n        'atx' => 'application/vnd.antix.game-component',\n        'au' => 'audio/x-au',\n        'avci' => 'image/avci',\n        'avcs' => 'image/avcs',\n        'avi' => 'video/x-msvideo',\n        'avif' => 'image/avif',\n        'aw' => 'application/applixware',\n        'azf' => 'application/vnd.airzip.filesecure.azf',\n        'azs' => 'application/vnd.airzip.filesecure.azs',\n        'azv' => 'image/vnd.airzip.accelerator.azv',\n        'azw' => 'application/vnd.amazon.ebook',\n        'b16' => 'image/vnd.pco.b16',\n        'bat' => 'application/x-msdownload',\n        'bcpio' => 'application/x-bcpio',\n        'bdf' => 'application/x-font-bdf',\n        'bdm' => 'application/vnd.syncml.dm+wbxml',\n        'bdoc' => 'application/x-bdoc',\n        'bed' => 'application/vnd.realvnc.bed',\n        'bh2' => 'application/vnd.fujitsu.oasysprs',\n        'bin' => 'application/octet-stream',\n        'blb' => 'application/x-blorb',\n        'blorb' => 'application/x-blorb',\n        'bmi' => 'application/vnd.bmi',\n        'bmml' => 'application/vnd.balsamiq.bmml+xml',\n        'bmp' => 'image/bmp',\n        'book' => 'application/vnd.framemaker',\n        'box' => 'application/vnd.previewsystems.box',\n        'boz' => 'application/x-bzip2',\n        'bpk' => 'application/octet-stream',\n        'bpmn' => 'application/octet-stream',\n        'bsp' => 'model/vnd.valve.source.compiled-map',\n        'btif' => 'image/prs.btif',\n        'buffer' => 'application/octet-stream',\n        'bz' => 'application/x-bzip',\n        'bz2' => 'application/x-bzip2',\n        'c' => 'text/x-c',\n        'c4d' => 'application/vnd.clonk.c4group',\n        'c4f' => 'application/vnd.clonk.c4group',\n        'c4g' => 'application/vnd.clonk.c4group',\n        'c4p' => 'application/vnd.clonk.c4group',\n        'c4u' => 'application/vnd.clonk.c4group',\n        'c11amc' => 'application/vnd.cluetrust.cartomobile-config',\n        'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',\n        'cab' => 'application/vnd.ms-cab-compressed',\n        'caf' => 'audio/x-caf',\n        'cap' => 'application/vnd.tcpdump.pcap',\n        'car' => 'application/vnd.curl.car',\n        'cat' => 'application/vnd.ms-pki.seccat',\n        'cb7' => 'application/x-cbr',\n        'cba' => 'application/x-cbr',\n        'cbr' => 'application/x-cbr',\n        'cbt' => 'application/x-cbr',\n        'cbz' => 'application/x-cbr',\n        'cc' => 'text/x-c',\n        'cco' => 'application/x-cocoa',\n        'cct' => 'application/x-director',\n        'ccxml' => 'application/ccxml+xml',\n        'cdbcmsg' => 'application/vnd.contact.cmsg',\n        'cdf' => 'application/x-netcdf',\n        'cdfx' => 'application/cdfx+xml',\n        'cdkey' => 'application/vnd.mediastation.cdkey',\n        'cdmia' => 'application/cdmi-capability',\n        'cdmic' => 'application/cdmi-container',\n        'cdmid' => 'application/cdmi-domain',\n        'cdmio' => 'application/cdmi-object',\n        'cdmiq' => 'application/cdmi-queue',\n        'cdr' => 'application/cdr',\n        'cdx' => 'chemical/x-cdx',\n        'cdxml' => 'application/vnd.chemdraw+xml',\n        'cdy' => 'application/vnd.cinderella',\n        'cer' => 'application/pkix-cert',\n        'cfs' => 'application/x-cfs-compressed',\n        'cgm' => 'image/cgm',\n        'chat' => 'application/x-chat',\n        'chm' => 'application/vnd.ms-htmlhelp',\n        'chrt' => 'application/vnd.kde.kchart',\n        'cif' => 'chemical/x-cif',\n        'cii' => 'application/vnd.anser-web-certificate-issue-initiation',\n        'cil' => 'application/vnd.ms-artgalry',\n        'cjs' => 'application/node',\n        'cla' => 'application/vnd.claymore',\n        'class' => 'application/octet-stream',\n        'clkk' => 'application/vnd.crick.clicker.keyboard',\n        'clkp' => 'application/vnd.crick.clicker.palette',\n        'clkt' => 'application/vnd.crick.clicker.template',\n        'clkw' => 'application/vnd.crick.clicker.wordbank',\n        'clkx' => 'application/vnd.crick.clicker',\n        'clp' => 'application/x-msclip',\n        'cmc' => 'application/vnd.cosmocaller',\n        'cmdf' => 'chemical/x-cmdf',\n        'cml' => 'chemical/x-cml',\n        'cmp' => 'application/vnd.yellowriver-custom-menu',\n        'cmx' => 'image/x-cmx',\n        'cod' => 'application/vnd.rim.cod',\n        'coffee' => 'text/coffeescript',\n        'com' => 'application/x-msdownload',\n        'conf' => 'text/plain',\n        'cpio' => 'application/x-cpio',\n        'cpl' => 'application/cpl+xml',\n        'cpp' => 'text/x-c',\n        'cpt' => 'application/mac-compactpro',\n        'crd' => 'application/x-mscardfile',\n        'crl' => 'application/pkix-crl',\n        'crt' => 'application/x-x509-ca-cert',\n        'crx' => 'application/x-chrome-extension',\n        'cryptonote' => 'application/vnd.rig.cryptonote',\n        'csh' => 'application/x-csh',\n        'csl' => 'application/vnd.citationstyles.style+xml',\n        'csml' => 'chemical/x-csml',\n        'csp' => 'application/vnd.commonspace',\n        'csr' => 'application/octet-stream',\n        'css' => 'text/css',\n        'cst' => 'application/x-director',\n        'csv' => 'text/csv',\n        'cu' => 'application/cu-seeme',\n        'curl' => 'text/vnd.curl',\n        'cww' => 'application/prs.cww',\n        'cxt' => 'application/x-director',\n        'cxx' => 'text/x-c',\n        'dae' => 'model/vnd.collada+xml',\n        'daf' => 'application/vnd.mobius.daf',\n        'dart' => 'application/vnd.dart',\n        'dataless' => 'application/vnd.fdsn.seed',\n        'davmount' => 'application/davmount+xml',\n        'dbf' => 'application/vnd.dbf',\n        'dbk' => 'application/docbook+xml',\n        'dcr' => 'application/x-director',\n        'dcurl' => 'text/vnd.curl.dcurl',\n        'dd2' => 'application/vnd.oma.dd2+xml',\n        'ddd' => 'application/vnd.fujixerox.ddd',\n        'ddf' => 'application/vnd.syncml.dmddf+xml',\n        'dds' => 'image/vnd.ms-dds',\n        'deb' => 'application/x-debian-package',\n        'def' => 'text/plain',\n        'deploy' => 'application/octet-stream',\n        'der' => 'application/x-x509-ca-cert',\n        'dfac' => 'application/vnd.dreamfactory',\n        'dgc' => 'application/x-dgc-compressed',\n        'dic' => 'text/x-c',\n        'dir' => 'application/x-director',\n        'dis' => 'application/vnd.mobius.dis',\n        'disposition-notification' => 'message/disposition-notification',\n        'dist' => 'application/octet-stream',\n        'distz' => 'application/octet-stream',\n        'djv' => 'image/vnd.djvu',\n        'djvu' => 'image/vnd.djvu',\n        'dll' => 'application/octet-stream',\n        'dmg' => 'application/x-apple-diskimage',\n        'dmn' => 'application/octet-stream',\n        'dmp' => 'application/vnd.tcpdump.pcap',\n        'dms' => 'application/octet-stream',\n        'dna' => 'application/vnd.dna',\n        'doc' => 'application/msword',\n        'docm' => 'application/vnd.ms-word.template.macroEnabled.12',\n        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n        'dot' => 'application/msword',\n        'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',\n        'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',\n        'dp' => 'application/vnd.osgi.dp',\n        'dpg' => 'application/vnd.dpgraph',\n        'dra' => 'audio/vnd.dra',\n        'drle' => 'image/dicom-rle',\n        'dsc' => 'text/prs.lines.tag',\n        'dssc' => 'application/dssc+der',\n        'dtb' => 'application/x-dtbook+xml',\n        'dtd' => 'application/xml-dtd',\n        'dts' => 'audio/vnd.dts',\n        'dtshd' => 'audio/vnd.dts.hd',\n        'dump' => 'application/octet-stream',\n        'dvb' => 'video/vnd.dvb.file',\n        'dvi' => 'application/x-dvi',\n        'dwd' => 'application/atsc-dwd+xml',\n        'dwf' => 'model/vnd.dwf',\n        'dwg' => 'image/vnd.dwg',\n        'dxf' => 'image/vnd.dxf',\n        'dxp' => 'application/vnd.spotfire.dxp',\n        'dxr' => 'application/x-director',\n        'ear' => 'application/java-archive',\n        'ecelp4800' => 'audio/vnd.nuera.ecelp4800',\n        'ecelp7470' => 'audio/vnd.nuera.ecelp7470',\n        'ecelp9600' => 'audio/vnd.nuera.ecelp9600',\n        'ecma' => 'application/ecmascript',\n        'edm' => 'application/vnd.novadigm.edm',\n        'edx' => 'application/vnd.novadigm.edx',\n        'efif' => 'application/vnd.picsel',\n        'ei6' => 'application/vnd.pg.osasli',\n        'elc' => 'application/octet-stream',\n        'emf' => 'image/emf',\n        'eml' => 'message/rfc822',\n        'emma' => 'application/emma+xml',\n        'emotionml' => 'application/emotionml+xml',\n        'emz' => 'application/x-msmetafile',\n        'eol' => 'audio/vnd.digital-winds',\n        'eot' => 'application/vnd.ms-fontobject',\n        'eps' => 'application/postscript',\n        'epub' => 'application/epub+zip',\n        'es' => 'application/ecmascript',\n        'es3' => 'application/vnd.eszigno3+xml',\n        'esa' => 'application/vnd.osgi.subsystem',\n        'esf' => 'application/vnd.epson.esf',\n        'et3' => 'application/vnd.eszigno3+xml',\n        'etx' => 'text/x-setext',\n        'eva' => 'application/x-eva',\n        'evy' => 'application/x-envoy',\n        'exe' => 'application/octet-stream',\n        'exi' => 'application/exi',\n        'exp' => 'application/express',\n        'exr' => 'image/aces',\n        'ext' => 'application/vnd.novadigm.ext',\n        'ez' => 'application/andrew-inset',\n        'ez2' => 'application/vnd.ezpix-album',\n        'ez3' => 'application/vnd.ezpix-package',\n        'f' => 'text/x-fortran',\n        'f4v' => 'video/mp4',\n        'f77' => 'text/x-fortran',\n        'f90' => 'text/x-fortran',\n        'fbs' => 'image/vnd.fastbidsheet',\n        'fcdt' => 'application/vnd.adobe.formscentral.fcdt',\n        'fcs' => 'application/vnd.isac.fcs',\n        'fdf' => 'application/vnd.fdf',\n        'fdt' => 'application/fdt+xml',\n        'fe_launch' => 'application/vnd.denovo.fcselayout-link',\n        'fg5' => 'application/vnd.fujitsu.oasysgp',\n        'fgd' => 'application/x-director',\n        'fh' => 'image/x-freehand',\n        'fh4' => 'image/x-freehand',\n        'fh5' => 'image/x-freehand',\n        'fh7' => 'image/x-freehand',\n        'fhc' => 'image/x-freehand',\n        'fig' => 'application/x-xfig',\n        'fits' => 'image/fits',\n        'flac' => 'audio/x-flac',\n        'fli' => 'video/x-fli',\n        'flo' => 'application/vnd.micrografx.flo',\n        'flv' => 'video/x-flv',\n        'flw' => 'application/vnd.kde.kivio',\n        'flx' => 'text/vnd.fmi.flexstor',\n        'fly' => 'text/vnd.fly',\n        'fm' => 'application/vnd.framemaker',\n        'fnc' => 'application/vnd.frogans.fnc',\n        'fo' => 'application/vnd.software602.filler.form+xml',\n        'for' => 'text/x-fortran',\n        'fpx' => 'image/vnd.fpx',\n        'frame' => 'application/vnd.framemaker',\n        'fsc' => 'application/vnd.fsc.weblaunch',\n        'fst' => 'image/vnd.fst',\n        'ftc' => 'application/vnd.fluxtime.clip',\n        'fti' => 'application/vnd.anser-web-funds-transfer-initiation',\n        'fvt' => 'video/vnd.fvt',\n        'fxp' => 'application/vnd.adobe.fxp',\n        'fxpl' => 'application/vnd.adobe.fxp',\n        'fzs' => 'application/vnd.fuzzysheet',\n        'g2w' => 'application/vnd.geoplan',\n        'g3' => 'image/g3fax',\n        'g3w' => 'application/vnd.geospace',\n        'gac' => 'application/vnd.groove-account',\n        'gam' => 'application/x-tads',\n        'gbr' => 'application/rpki-ghostbusters',\n        'gca' => 'application/x-gca-compressed',\n        'gdl' => 'model/vnd.gdl',\n        'gdoc' => 'application/vnd.google-apps.document',\n        'ged' => 'text/vnd.familysearch.gedcom',\n        'geo' => 'application/vnd.dynageo',\n        'geojson' => 'application/geo+json',\n        'gex' => 'application/vnd.geometry-explorer',\n        'ggb' => 'application/vnd.geogebra.file',\n        'ggt' => 'application/vnd.geogebra.tool',\n        'ghf' => 'application/vnd.groove-help',\n        'gif' => 'image/gif',\n        'gim' => 'application/vnd.groove-identity-message',\n        'glb' => 'model/gltf-binary',\n        'gltf' => 'model/gltf+json',\n        'gml' => 'application/gml+xml',\n        'gmx' => 'application/vnd.gmx',\n        'gnumeric' => 'application/x-gnumeric',\n        'gpg' => 'application/gpg-keys',\n        'gph' => 'application/vnd.flographit',\n        'gpx' => 'application/gpx+xml',\n        'gqf' => 'application/vnd.grafeq',\n        'gqs' => 'application/vnd.grafeq',\n        'gram' => 'application/srgs',\n        'gramps' => 'application/x-gramps-xml',\n        'gre' => 'application/vnd.geometry-explorer',\n        'grv' => 'application/vnd.groove-injector',\n        'grxml' => 'application/srgs+xml',\n        'gsf' => 'application/x-font-ghostscript',\n        'gsheet' => 'application/vnd.google-apps.spreadsheet',\n        'gslides' => 'application/vnd.google-apps.presentation',\n        'gtar' => 'application/x-gtar',\n        'gtm' => 'application/vnd.groove-tool-message',\n        'gtw' => 'model/vnd.gtw',\n        'gv' => 'text/vnd.graphviz',\n        'gxf' => 'application/gxf',\n        'gxt' => 'application/vnd.geonext',\n        'gz' => 'application/gzip',\n        'gzip' => 'application/gzip',\n        'h' => 'text/x-c',\n        'h261' => 'video/h261',\n        'h263' => 'video/h263',\n        'h264' => 'video/h264',\n        'hal' => 'application/vnd.hal+xml',\n        'hbci' => 'application/vnd.hbci',\n        'hbs' => 'text/x-handlebars-template',\n        'hdd' => 'application/x-virtualbox-hdd',\n        'hdf' => 'application/x-hdf',\n        'heic' => 'image/heic',\n        'heics' => 'image/heic-sequence',\n        'heif' => 'image/heif',\n        'heifs' => 'image/heif-sequence',\n        'hej2' => 'image/hej2k',\n        'held' => 'application/atsc-held+xml',\n        'hh' => 'text/x-c',\n        'hjson' => 'application/hjson',\n        'hlp' => 'application/winhlp',\n        'hpgl' => 'application/vnd.hp-hpgl',\n        'hpid' => 'application/vnd.hp-hpid',\n        'hps' => 'application/vnd.hp-hps',\n        'hqx' => 'application/mac-binhex40',\n        'hsj2' => 'image/hsj2',\n        'htc' => 'text/x-component',\n        'htke' => 'application/vnd.kenameaapp',\n        'htm' => 'text/html',\n        'html' => 'text/html',\n        'hvd' => 'application/vnd.yamaha.hv-dic',\n        'hvp' => 'application/vnd.yamaha.hv-voice',\n        'hvs' => 'application/vnd.yamaha.hv-script',\n        'i2g' => 'application/vnd.intergeo',\n        'icc' => 'application/vnd.iccprofile',\n        'ice' => 'x-conference/x-cooltalk',\n        'icm' => 'application/vnd.iccprofile',\n        'ico' => 'image/x-icon',\n        'ics' => 'text/calendar',\n        'ief' => 'image/ief',\n        'ifb' => 'text/calendar',\n        'ifm' => 'application/vnd.shana.informed.formdata',\n        'iges' => 'model/iges',\n        'igl' => 'application/vnd.igloader',\n        'igm' => 'application/vnd.insors.igm',\n        'igs' => 'model/iges',\n        'igx' => 'application/vnd.micrografx.igx',\n        'iif' => 'application/vnd.shana.informed.interchange',\n        'img' => 'application/octet-stream',\n        'imp' => 'application/vnd.accpac.simply.imp',\n        'ims' => 'application/vnd.ms-ims',\n        'in' => 'text/plain',\n        'ini' => 'text/plain',\n        'ink' => 'application/inkml+xml',\n        'inkml' => 'application/inkml+xml',\n        'install' => 'application/x-install-instructions',\n        'iota' => 'application/vnd.astraea-software.iota',\n        'ipfix' => 'application/ipfix',\n        'ipk' => 'application/vnd.shana.informed.package',\n        'irm' => 'application/vnd.ibm.rights-management',\n        'irp' => 'application/vnd.irepository.package+xml',\n        'iso' => 'application/x-iso9660-image',\n        'itp' => 'application/vnd.shana.informed.formtemplate',\n        'its' => 'application/its+xml',\n        'ivp' => 'application/vnd.immervision-ivp',\n        'ivu' => 'application/vnd.immervision-ivu',\n        'jad' => 'text/vnd.sun.j2me.app-descriptor',\n        'jade' => 'text/jade',\n        'jam' => 'application/vnd.jam',\n        'jar' => 'application/java-archive',\n        'jardiff' => 'application/x-java-archive-diff',\n        'java' => 'text/x-java-source',\n        'jhc' => 'image/jphc',\n        'jisp' => 'application/vnd.jisp',\n        'jls' => 'image/jls',\n        'jlt' => 'application/vnd.hp-jlyt',\n        'jng' => 'image/x-jng',\n        'jnlp' => 'application/x-java-jnlp-file',\n        'joda' => 'application/vnd.joost.joda-archive',\n        'jp2' => 'image/jp2',\n        'jpe' => 'image/jpeg',\n        'jpeg' => 'image/jpeg',\n        'jpf' => 'image/jpx',\n        'jpg' => 'image/jpeg',\n        'jpg2' => 'image/jp2',\n        'jpgm' => 'video/jpm',\n        'jpgv' => 'video/jpeg',\n        'jph' => 'image/jph',\n        'jpm' => 'video/jpm',\n        'jpx' => 'image/jpx',\n        'js' => 'application/javascript',\n        'json' => 'application/json',\n        'json5' => 'application/json5',\n        'jsonld' => 'application/ld+json',\n        'jsonml' => 'application/jsonml+json',\n        'jsx' => 'text/jsx',\n        'jxr' => 'image/jxr',\n        'jxra' => 'image/jxra',\n        'jxrs' => 'image/jxrs',\n        'jxs' => 'image/jxs',\n        'jxsc' => 'image/jxsc',\n        'jxsi' => 'image/jxsi',\n        'jxss' => 'image/jxss',\n        'kar' => 'audio/midi',\n        'karbon' => 'application/vnd.kde.karbon',\n        'kdb' => 'application/octet-stream',\n        'kdbx' => 'application/x-keepass2',\n        'key' => 'application/x-iwork-keynote-sffkey',\n        'kfo' => 'application/vnd.kde.kformula',\n        'kia' => 'application/vnd.kidspiration',\n        'kml' => 'application/vnd.google-earth.kml+xml',\n        'kmz' => 'application/vnd.google-earth.kmz',\n        'kne' => 'application/vnd.kinar',\n        'knp' => 'application/vnd.kinar',\n        'kon' => 'application/vnd.kde.kontour',\n        'kpr' => 'application/vnd.kde.kpresenter',\n        'kpt' => 'application/vnd.kde.kpresenter',\n        'kpxx' => 'application/vnd.ds-keypoint',\n        'ksp' => 'application/vnd.kde.kspread',\n        'ktr' => 'application/vnd.kahootz',\n        'ktx' => 'image/ktx',\n        'ktx2' => 'image/ktx2',\n        'ktz' => 'application/vnd.kahootz',\n        'kwd' => 'application/vnd.kde.kword',\n        'kwt' => 'application/vnd.kde.kword',\n        'lasxml' => 'application/vnd.las.las+xml',\n        'latex' => 'application/x-latex',\n        'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',\n        'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',\n        'les' => 'application/vnd.hhe.lesson-player',\n        'less' => 'text/less',\n        'lgr' => 'application/lgr+xml',\n        'lha' => 'application/octet-stream',\n        'link66' => 'application/vnd.route66.link66+xml',\n        'list' => 'text/plain',\n        'list3820' => 'application/vnd.ibm.modcap',\n        'listafp' => 'application/vnd.ibm.modcap',\n        'litcoffee' => 'text/coffeescript',\n        'lnk' => 'application/x-ms-shortcut',\n        'log' => 'text/plain',\n        'lostxml' => 'application/lost+xml',\n        'lrf' => 'application/octet-stream',\n        'lrm' => 'application/vnd.ms-lrm',\n        'ltf' => 'application/vnd.frogans.ltf',\n        'lua' => 'text/x-lua',\n        'luac' => 'application/x-lua-bytecode',\n        'lvp' => 'audio/vnd.lucent.voice',\n        'lwp' => 'application/vnd.lotus-wordpro',\n        'lzh' => 'application/octet-stream',\n        'm1v' => 'video/mpeg',\n        'm2a' => 'audio/mpeg',\n        'm2v' => 'video/mpeg',\n        'm3a' => 'audio/mpeg',\n        'm3u' => 'text/plain',\n        'm3u8' => 'application/vnd.apple.mpegurl',\n        'm4a' => 'audio/x-m4a',\n        'm4p' => 'application/mp4',\n        'm4s' => 'video/iso.segment',\n        'm4u' => 'application/vnd.mpegurl',\n        'm4v' => 'video/x-m4v',\n        'm13' => 'application/x-msmediaview',\n        'm14' => 'application/x-msmediaview',\n        'm21' => 'application/mp21',\n        'ma' => 'application/mathematica',\n        'mads' => 'application/mads+xml',\n        'maei' => 'application/mmt-aei+xml',\n        'mag' => 'application/vnd.ecowin.chart',\n        'maker' => 'application/vnd.framemaker',\n        'man' => 'text/troff',\n        'manifest' => 'text/cache-manifest',\n        'map' => 'application/json',\n        'mar' => 'application/octet-stream',\n        'markdown' => 'text/markdown',\n        'mathml' => 'application/mathml+xml',\n        'mb' => 'application/mathematica',\n        'mbk' => 'application/vnd.mobius.mbk',\n        'mbox' => 'application/mbox',\n        'mc1' => 'application/vnd.medcalcdata',\n        'mcd' => 'application/vnd.mcd',\n        'mcurl' => 'text/vnd.curl.mcurl',\n        'md' => 'text/markdown',\n        'mdb' => 'application/x-msaccess',\n        'mdi' => 'image/vnd.ms-modi',\n        'mdx' => 'text/mdx',\n        'me' => 'text/troff',\n        'mesh' => 'model/mesh',\n        'meta4' => 'application/metalink4+xml',\n        'metalink' => 'application/metalink+xml',\n        'mets' => 'application/mets+xml',\n        'mfm' => 'application/vnd.mfmp',\n        'mft' => 'application/rpki-manifest',\n        'mgp' => 'application/vnd.osgeo.mapguide.package',\n        'mgz' => 'application/vnd.proteus.magazine',\n        'mid' => 'audio/midi',\n        'midi' => 'audio/midi',\n        'mie' => 'application/x-mie',\n        'mif' => 'application/vnd.mif',\n        'mime' => 'message/rfc822',\n        'mj2' => 'video/mj2',\n        'mjp2' => 'video/mj2',\n        'mjs' => 'application/javascript',\n        'mk3d' => 'video/x-matroska',\n        'mka' => 'audio/x-matroska',\n        'mkd' => 'text/x-markdown',\n        'mks' => 'video/x-matroska',\n        'mkv' => 'video/x-matroska',\n        'mlp' => 'application/vnd.dolby.mlp',\n        'mmd' => 'application/vnd.chipnuts.karaoke-mmd',\n        'mmf' => 'application/vnd.smaf',\n        'mml' => 'text/mathml',\n        'mmr' => 'image/vnd.fujixerox.edmics-mmr',\n        'mng' => 'video/x-mng',\n        'mny' => 'application/x-msmoney',\n        'mobi' => 'application/x-mobipocket-ebook',\n        'mods' => 'application/mods+xml',\n        'mov' => 'video/quicktime',\n        'movie' => 'video/x-sgi-movie',\n        'mp2' => 'audio/mpeg',\n        'mp2a' => 'audio/mpeg',\n        'mp3' => 'audio/mpeg',\n        'mp4' => 'video/mp4',\n        'mp4a' => 'audio/mp4',\n        'mp4s' => 'application/mp4',\n        'mp4v' => 'video/mp4',\n        'mp21' => 'application/mp21',\n        'mpc' => 'application/vnd.mophun.certificate',\n        'mpd' => 'application/dash+xml',\n        'mpe' => 'video/mpeg',\n        'mpeg' => 'video/mpeg',\n        'mpf' => 'application/media-policy-dataset+xml',\n        'mpg' => 'video/mpeg',\n        'mpg4' => 'video/mp4',\n        'mpga' => 'audio/mpeg',\n        'mpkg' => 'application/vnd.apple.installer+xml',\n        'mpm' => 'application/vnd.blueice.multipass',\n        'mpn' => 'application/vnd.mophun.application',\n        'mpp' => 'application/vnd.ms-project',\n        'mpt' => 'application/vnd.ms-project',\n        'mpy' => 'application/vnd.ibm.minipay',\n        'mqy' => 'application/vnd.mobius.mqy',\n        'mrc' => 'application/marc',\n        'mrcx' => 'application/marcxml+xml',\n        'ms' => 'text/troff',\n        'mscml' => 'application/mediaservercontrol+xml',\n        'mseed' => 'application/vnd.fdsn.mseed',\n        'mseq' => 'application/vnd.mseq',\n        'msf' => 'application/vnd.epson.msf',\n        'msg' => 'application/vnd.ms-outlook',\n        'msh' => 'model/mesh',\n        'msi' => 'application/x-msdownload',\n        'msl' => 'application/vnd.mobius.msl',\n        'msm' => 'application/octet-stream',\n        'msp' => 'application/octet-stream',\n        'msty' => 'application/vnd.muvee.style',\n        'mtl' => 'model/mtl',\n        'mts' => 'model/vnd.mts',\n        'mus' => 'application/vnd.musician',\n        'musd' => 'application/mmt-usd+xml',\n        'musicxml' => 'application/vnd.recordare.musicxml+xml',\n        'mvb' => 'application/x-msmediaview',\n        'mvt' => 'application/vnd.mapbox-vector-tile',\n        'mwf' => 'application/vnd.mfer',\n        'mxf' => 'application/mxf',\n        'mxl' => 'application/vnd.recordare.musicxml',\n        'mxmf' => 'audio/mobile-xmf',\n        'mxml' => 'application/xv+xml',\n        'mxs' => 'application/vnd.triscape.mxs',\n        'mxu' => 'video/vnd.mpegurl',\n        'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',\n        'n3' => 'text/n3',\n        'nb' => 'application/mathematica',\n        'nbp' => 'application/vnd.wolfram.player',\n        'nc' => 'application/x-netcdf',\n        'ncx' => 'application/x-dtbncx+xml',\n        'nfo' => 'text/x-nfo',\n        'ngdat' => 'application/vnd.nokia.n-gage.data',\n        'nitf' => 'application/vnd.nitf',\n        'nlu' => 'application/vnd.neurolanguage.nlu',\n        'nml' => 'application/vnd.enliven',\n        'nnd' => 'application/vnd.noblenet-directory',\n        'nns' => 'application/vnd.noblenet-sealer',\n        'nnw' => 'application/vnd.noblenet-web',\n        'npx' => 'image/vnd.net-fpx',\n        'nq' => 'application/n-quads',\n        'nsc' => 'application/x-conference',\n        'nsf' => 'application/vnd.lotus-notes',\n        'nt' => 'application/n-triples',\n        'ntf' => 'application/vnd.nitf',\n        'numbers' => 'application/x-iwork-numbers-sffnumbers',\n        'nzb' => 'application/x-nzb',\n        'oa2' => 'application/vnd.fujitsu.oasys2',\n        'oa3' => 'application/vnd.fujitsu.oasys3',\n        'oas' => 'application/vnd.fujitsu.oasys',\n        'obd' => 'application/x-msbinder',\n        'obgx' => 'application/vnd.openblox.game+xml',\n        'obj' => 'model/obj',\n        'oda' => 'application/oda',\n        'odb' => 'application/vnd.oasis.opendocument.database',\n        'odc' => 'application/vnd.oasis.opendocument.chart',\n        'odf' => 'application/vnd.oasis.opendocument.formula',\n        'odft' => 'application/vnd.oasis.opendocument.formula-template',\n        'odg' => 'application/vnd.oasis.opendocument.graphics',\n        'odi' => 'application/vnd.oasis.opendocument.image',\n        'odm' => 'application/vnd.oasis.opendocument.text-master',\n        'odp' => 'application/vnd.oasis.opendocument.presentation',\n        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',\n        'odt' => 'application/vnd.oasis.opendocument.text',\n        'oga' => 'audio/ogg',\n        'ogex' => 'model/vnd.opengex',\n        'ogg' => 'audio/ogg',\n        'ogv' => 'video/ogg',\n        'ogx' => 'application/ogg',\n        'omdoc' => 'application/omdoc+xml',\n        'onepkg' => 'application/onenote',\n        'onetmp' => 'application/onenote',\n        'onetoc' => 'application/onenote',\n        'onetoc2' => 'application/onenote',\n        'opf' => 'application/oebps-package+xml',\n        'opml' => 'text/x-opml',\n        'oprc' => 'application/vnd.palm',\n        'opus' => 'audio/ogg',\n        'org' => 'text/x-org',\n        'osf' => 'application/vnd.yamaha.openscoreformat',\n        'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',\n        'osm' => 'application/vnd.openstreetmap.data+xml',\n        'otc' => 'application/vnd.oasis.opendocument.chart-template',\n        'otf' => 'font/otf',\n        'otg' => 'application/vnd.oasis.opendocument.graphics-template',\n        'oth' => 'application/vnd.oasis.opendocument.text-web',\n        'oti' => 'application/vnd.oasis.opendocument.image-template',\n        'otp' => 'application/vnd.oasis.opendocument.presentation-template',\n        'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',\n        'ott' => 'application/vnd.oasis.opendocument.text-template',\n        'ova' => 'application/x-virtualbox-ova',\n        'ovf' => 'application/x-virtualbox-ovf',\n        'owl' => 'application/rdf+xml',\n        'oxps' => 'application/oxps',\n        'oxt' => 'application/vnd.openofficeorg.extension',\n        'p' => 'text/x-pascal',\n        'p7a' => 'application/x-pkcs7-signature',\n        'p7b' => 'application/x-pkcs7-certificates',\n        'p7c' => 'application/pkcs7-mime',\n        'p7m' => 'application/pkcs7-mime',\n        'p7r' => 'application/x-pkcs7-certreqresp',\n        'p7s' => 'application/pkcs7-signature',\n        'p8' => 'application/pkcs8',\n        'p10' => 'application/x-pkcs10',\n        'p12' => 'application/x-pkcs12',\n        'pac' => 'application/x-ns-proxy-autoconfig',\n        'pages' => 'application/x-iwork-pages-sffpages',\n        'pas' => 'text/x-pascal',\n        'paw' => 'application/vnd.pawaafile',\n        'pbd' => 'application/vnd.powerbuilder6',\n        'pbm' => 'image/x-portable-bitmap',\n        'pcap' => 'application/vnd.tcpdump.pcap',\n        'pcf' => 'application/x-font-pcf',\n        'pcl' => 'application/vnd.hp-pcl',\n        'pclxl' => 'application/vnd.hp-pclxl',\n        'pct' => 'image/x-pict',\n        'pcurl' => 'application/vnd.curl.pcurl',\n        'pcx' => 'image/x-pcx',\n        'pdb' => 'application/x-pilot',\n        'pde' => 'text/x-processing',\n        'pdf' => 'application/pdf',\n        'pem' => 'application/x-x509-user-cert',\n        'pfa' => 'application/x-font-type1',\n        'pfb' => 'application/x-font-type1',\n        'pfm' => 'application/x-font-type1',\n        'pfr' => 'application/font-tdpfr',\n        'pfx' => 'application/x-pkcs12',\n        'pgm' => 'image/x-portable-graymap',\n        'pgn' => 'application/x-chess-pgn',\n        'pgp' => 'application/pgp',\n        'php' => 'application/x-httpd-php',\n        'php3' => 'application/x-httpd-php',\n        'php4' => 'application/x-httpd-php',\n        'phps' => 'application/x-httpd-php-source',\n        'phtml' => 'application/x-httpd-php',\n        'pic' => 'image/x-pict',\n        'pkg' => 'application/octet-stream',\n        'pki' => 'application/pkixcmp',\n        'pkipath' => 'application/pkix-pkipath',\n        'pkpass' => 'application/vnd.apple.pkpass',\n        'pl' => 'application/x-perl',\n        'plb' => 'application/vnd.3gpp.pic-bw-large',\n        'plc' => 'application/vnd.mobius.plc',\n        'plf' => 'application/vnd.pocketlearn',\n        'pls' => 'application/pls+xml',\n        'pm' => 'application/x-perl',\n        'pml' => 'application/vnd.ctc-posml',\n        'png' => 'image/png',\n        'pnm' => 'image/x-portable-anymap',\n        'portpkg' => 'application/vnd.macports.portpkg',\n        'pot' => 'application/vnd.ms-powerpoint',\n        'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',\n        'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',\n        'ppa' => 'application/vnd.ms-powerpoint',\n        'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',\n        'ppd' => 'application/vnd.cups-ppd',\n        'ppm' => 'image/x-portable-pixmap',\n        'pps' => 'application/vnd.ms-powerpoint',\n        'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',\n        'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',\n        'ppt' => 'application/powerpoint',\n        'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',\n        'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n        'pqa' => 'application/vnd.palm',\n        'prc' => 'model/prc',\n        'pre' => 'application/vnd.lotus-freelance',\n        'prf' => 'application/pics-rules',\n        'provx' => 'application/provenance+xml',\n        'ps' => 'application/postscript',\n        'psb' => 'application/vnd.3gpp.pic-bw-small',\n        'psd' => 'application/x-photoshop',\n        'psf' => 'application/x-font-linux-psf',\n        'pskcxml' => 'application/pskc+xml',\n        'pti' => 'image/prs.pti',\n        'ptid' => 'application/vnd.pvi.ptid1',\n        'pub' => 'application/x-mspublisher',\n        'pvb' => 'application/vnd.3gpp.pic-bw-var',\n        'pwn' => 'application/vnd.3m.post-it-notes',\n        'pya' => 'audio/vnd.ms-playready.media.pya',\n        'pyv' => 'video/vnd.ms-playready.media.pyv',\n        'qam' => 'application/vnd.epson.quickanime',\n        'qbo' => 'application/vnd.intu.qbo',\n        'qfx' => 'application/vnd.intu.qfx',\n        'qps' => 'application/vnd.publishare-delta-tree',\n        'qt' => 'video/quicktime',\n        'qwd' => 'application/vnd.quark.quarkxpress',\n        'qwt' => 'application/vnd.quark.quarkxpress',\n        'qxb' => 'application/vnd.quark.quarkxpress',\n        'qxd' => 'application/vnd.quark.quarkxpress',\n        'qxl' => 'application/vnd.quark.quarkxpress',\n        'qxt' => 'application/vnd.quark.quarkxpress',\n        'ra' => 'audio/x-realaudio',\n        'ram' => 'audio/x-pn-realaudio',\n        'raml' => 'application/raml+yaml',\n        'rapd' => 'application/route-apd+xml',\n        'rar' => 'application/x-rar',\n        'ras' => 'image/x-cmu-raster',\n        'rcprofile' => 'application/vnd.ipunplugged.rcprofile',\n        'rdf' => 'application/rdf+xml',\n        'rdz' => 'application/vnd.data-vision.rdz',\n        'relo' => 'application/p2p-overlay+xml',\n        'rep' => 'application/vnd.businessobjects',\n        'res' => 'application/x-dtbresource+xml',\n        'rgb' => 'image/x-rgb',\n        'rif' => 'application/reginfo+xml',\n        'rip' => 'audio/vnd.rip',\n        'ris' => 'application/x-research-info-systems',\n        'rl' => 'application/resource-lists+xml',\n        'rlc' => 'image/vnd.fujixerox.edmics-rlc',\n        'rld' => 'application/resource-lists-diff+xml',\n        'rm' => 'audio/x-pn-realaudio',\n        'rmi' => 'audio/midi',\n        'rmp' => 'audio/x-pn-realaudio-plugin',\n        'rms' => 'application/vnd.jcp.javame.midlet-rms',\n        'rmvb' => 'application/vnd.rn-realmedia-vbr',\n        'rnc' => 'application/relax-ng-compact-syntax',\n        'rng' => 'application/xml',\n        'roa' => 'application/rpki-roa',\n        'roff' => 'text/troff',\n        'rp9' => 'application/vnd.cloanto.rp9',\n        'rpm' => 'audio/x-pn-realaudio-plugin',\n        'rpss' => 'application/vnd.nokia.radio-presets',\n        'rpst' => 'application/vnd.nokia.radio-preset',\n        'rq' => 'application/sparql-query',\n        'rs' => 'application/rls-services+xml',\n        'rsa' => 'application/x-pkcs7',\n        'rsat' => 'application/atsc-rsat+xml',\n        'rsd' => 'application/rsd+xml',\n        'rsheet' => 'application/urc-ressheet+xml',\n        'rss' => 'application/rss+xml',\n        'rtf' => 'text/rtf',\n        'rtx' => 'text/richtext',\n        'run' => 'application/x-makeself',\n        'rusd' => 'application/route-usd+xml',\n        'rv' => 'video/vnd.rn-realvideo',\n        's' => 'text/x-asm',\n        's3m' => 'audio/s3m',\n        'saf' => 'application/vnd.yamaha.smaf-audio',\n        'sass' => 'text/x-sass',\n        'sbml' => 'application/sbml+xml',\n        'sc' => 'application/vnd.ibm.secure-container',\n        'scd' => 'application/x-msschedule',\n        'scm' => 'application/vnd.lotus-screencam',\n        'scq' => 'application/scvp-cv-request',\n        'scs' => 'application/scvp-cv-response',\n        'scss' => 'text/x-scss',\n        'scurl' => 'text/vnd.curl.scurl',\n        'sda' => 'application/vnd.stardivision.draw',\n        'sdc' => 'application/vnd.stardivision.calc',\n        'sdd' => 'application/vnd.stardivision.impress',\n        'sdkd' => 'application/vnd.solent.sdkm+xml',\n        'sdkm' => 'application/vnd.solent.sdkm+xml',\n        'sdp' => 'application/sdp',\n        'sdw' => 'application/vnd.stardivision.writer',\n        'sea' => 'application/octet-stream',\n        'see' => 'application/vnd.seemail',\n        'seed' => 'application/vnd.fdsn.seed',\n        'sema' => 'application/vnd.sema',\n        'semd' => 'application/vnd.semd',\n        'semf' => 'application/vnd.semf',\n        'senmlx' => 'application/senml+xml',\n        'sensmlx' => 'application/sensml+xml',\n        'ser' => 'application/java-serialized-object',\n        'setpay' => 'application/set-payment-initiation',\n        'setreg' => 'application/set-registration-initiation',\n        'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',\n        'sfs' => 'application/vnd.spotfire.sfs',\n        'sfv' => 'text/x-sfv',\n        'sgi' => 'image/sgi',\n        'sgl' => 'application/vnd.stardivision.writer-global',\n        'sgm' => 'text/sgml',\n        'sgml' => 'text/sgml',\n        'sh' => 'application/x-sh',\n        'shar' => 'application/x-shar',\n        'shex' => 'text/shex',\n        'shf' => 'application/shf+xml',\n        'shtml' => 'text/html',\n        'sid' => 'image/x-mrsid-image',\n        'sieve' => 'application/sieve',\n        'sig' => 'application/pgp-signature',\n        'sil' => 'audio/silk',\n        'silo' => 'model/mesh',\n        'sis' => 'application/vnd.symbian.install',\n        'sisx' => 'application/vnd.symbian.install',\n        'sit' => 'application/x-stuffit',\n        'sitx' => 'application/x-stuffitx',\n        'siv' => 'application/sieve',\n        'skd' => 'application/vnd.koan',\n        'skm' => 'application/vnd.koan',\n        'skp' => 'application/vnd.koan',\n        'skt' => 'application/vnd.koan',\n        'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',\n        'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',\n        'slim' => 'text/slim',\n        'slm' => 'text/slim',\n        'sls' => 'application/route-s-tsid+xml',\n        'slt' => 'application/vnd.epson.salt',\n        'sm' => 'application/vnd.stepmania.stepchart',\n        'smf' => 'application/vnd.stardivision.math',\n        'smi' => 'application/smil',\n        'smil' => 'application/smil',\n        'smv' => 'video/x-smv',\n        'smzip' => 'application/vnd.stepmania.package',\n        'snd' => 'audio/basic',\n        'snf' => 'application/x-font-snf',\n        'so' => 'application/octet-stream',\n        'spc' => 'application/x-pkcs7-certificates',\n        'spdx' => 'text/spdx',\n        'spf' => 'application/vnd.yamaha.smaf-phrase',\n        'spl' => 'application/x-futuresplash',\n        'spot' => 'text/vnd.in3d.spot',\n        'spp' => 'application/scvp-vp-response',\n        'spq' => 'application/scvp-vp-request',\n        'spx' => 'audio/ogg',\n        'sql' => 'application/x-sql',\n        'src' => 'application/x-wais-source',\n        'srt' => 'application/x-subrip',\n        'sru' => 'application/sru+xml',\n        'srx' => 'application/sparql-results+xml',\n        'ssdl' => 'application/ssdl+xml',\n        'sse' => 'application/vnd.kodak-descriptor',\n        'ssf' => 'application/vnd.epson.ssf',\n        'ssml' => 'application/ssml+xml',\n        'sst' => 'application/octet-stream',\n        'st' => 'application/vnd.sailingtracker.track',\n        'stc' => 'application/vnd.sun.xml.calc.template',\n        'std' => 'application/vnd.sun.xml.draw.template',\n        'stf' => 'application/vnd.wt.stf',\n        'sti' => 'application/vnd.sun.xml.impress.template',\n        'stk' => 'application/hyperstudio',\n        'stl' => 'model/stl',\n        'stpx' => 'model/step+xml',\n        'stpxz' => 'model/step-xml+zip',\n        'stpz' => 'model/step+zip',\n        'str' => 'application/vnd.pg.format',\n        'stw' => 'application/vnd.sun.xml.writer.template',\n        'styl' => 'text/stylus',\n        'stylus' => 'text/stylus',\n        'sub' => 'text/vnd.dvb.subtitle',\n        'sus' => 'application/vnd.sus-calendar',\n        'susp' => 'application/vnd.sus-calendar',\n        'sv4cpio' => 'application/x-sv4cpio',\n        'sv4crc' => 'application/x-sv4crc',\n        'svc' => 'application/vnd.dvb.service',\n        'svd' => 'application/vnd.svd',\n        'svg' => 'image/svg+xml',\n        'svgz' => 'image/svg+xml',\n        'swa' => 'application/x-director',\n        'swf' => 'application/x-shockwave-flash',\n        'swi' => 'application/vnd.aristanetworks.swi',\n        'swidtag' => 'application/swid+xml',\n        'sxc' => 'application/vnd.sun.xml.calc',\n        'sxd' => 'application/vnd.sun.xml.draw',\n        'sxg' => 'application/vnd.sun.xml.writer.global',\n        'sxi' => 'application/vnd.sun.xml.impress',\n        'sxm' => 'application/vnd.sun.xml.math',\n        'sxw' => 'application/vnd.sun.xml.writer',\n        't' => 'text/troff',\n        't3' => 'application/x-t3vm-image',\n        't38' => 'image/t38',\n        'taglet' => 'application/vnd.mynfc',\n        'tao' => 'application/vnd.tao.intent-module-archive',\n        'tap' => 'image/vnd.tencent.tap',\n        'tar' => 'application/x-tar',\n        'tcap' => 'application/vnd.3gpp2.tcap',\n        'tcl' => 'application/x-tcl',\n        'td' => 'application/urc-targetdesc+xml',\n        'teacher' => 'application/vnd.smart.teacher',\n        'tei' => 'application/tei+xml',\n        'teicorpus' => 'application/tei+xml',\n        'tex' => 'application/x-tex',\n        'texi' => 'application/x-texinfo',\n        'texinfo' => 'application/x-texinfo',\n        'text' => 'text/plain',\n        'tfi' => 'application/thraud+xml',\n        'tfm' => 'application/x-tex-tfm',\n        'tfx' => 'image/tiff-fx',\n        'tga' => 'image/x-tga',\n        'tgz' => 'application/x-tar',\n        'thmx' => 'application/vnd.ms-officetheme',\n        'tif' => 'image/tiff',\n        'tiff' => 'image/tiff',\n        'tk' => 'application/x-tcl',\n        'tmo' => 'application/vnd.tmobile-livetv',\n        'toml' => 'application/toml',\n        'torrent' => 'application/x-bittorrent',\n        'tpl' => 'application/vnd.groove-tool-template',\n        'tpt' => 'application/vnd.trid.tpt',\n        'tr' => 'text/troff',\n        'tra' => 'application/vnd.trueapp',\n        'trig' => 'application/trig',\n        'trm' => 'application/x-msterminal',\n        'ts' => 'video/mp2t',\n        'tsd' => 'application/timestamped-data',\n        'tsv' => 'text/tab-separated-values',\n        'ttc' => 'font/collection',\n        'ttf' => 'font/ttf',\n        'ttl' => 'text/turtle',\n        'ttml' => 'application/ttml+xml',\n        'twd' => 'application/vnd.simtech-mindmapper',\n        'twds' => 'application/vnd.simtech-mindmapper',\n        'txd' => 'application/vnd.genomatix.tuxedo',\n        'txf' => 'application/vnd.mobius.txf',\n        'txt' => 'text/plain',\n        'u3d' => 'model/u3d',\n        'u8dsn' => 'message/global-delivery-status',\n        'u8hdr' => 'message/global-headers',\n        'u8mdn' => 'message/global-disposition-notification',\n        'u8msg' => 'message/global',\n        'u32' => 'application/x-authorware-bin',\n        'ubj' => 'application/ubjson',\n        'udeb' => 'application/x-debian-package',\n        'ufd' => 'application/vnd.ufdl',\n        'ufdl' => 'application/vnd.ufdl',\n        'ulx' => 'application/x-glulx',\n        'umj' => 'application/vnd.umajin',\n        'unityweb' => 'application/vnd.unity',\n        'uoml' => 'application/vnd.uoml+xml',\n        'uri' => 'text/uri-list',\n        'uris' => 'text/uri-list',\n        'urls' => 'text/uri-list',\n        'usdz' => 'model/vnd.usdz+zip',\n        'ustar' => 'application/x-ustar',\n        'utz' => 'application/vnd.uiq.theme',\n        'uu' => 'text/x-uuencode',\n        'uva' => 'audio/vnd.dece.audio',\n        'uvd' => 'application/vnd.dece.data',\n        'uvf' => 'application/vnd.dece.data',\n        'uvg' => 'image/vnd.dece.graphic',\n        'uvh' => 'video/vnd.dece.hd',\n        'uvi' => 'image/vnd.dece.graphic',\n        'uvm' => 'video/vnd.dece.mobile',\n        'uvp' => 'video/vnd.dece.pd',\n        'uvs' => 'video/vnd.dece.sd',\n        'uvt' => 'application/vnd.dece.ttml+xml',\n        'uvu' => 'video/vnd.uvvu.mp4',\n        'uvv' => 'video/vnd.dece.video',\n        'uvva' => 'audio/vnd.dece.audio',\n        'uvvd' => 'application/vnd.dece.data',\n        'uvvf' => 'application/vnd.dece.data',\n        'uvvg' => 'image/vnd.dece.graphic',\n        'uvvh' => 'video/vnd.dece.hd',\n        'uvvi' => 'image/vnd.dece.graphic',\n        'uvvm' => 'video/vnd.dece.mobile',\n        'uvvp' => 'video/vnd.dece.pd',\n        'uvvs' => 'video/vnd.dece.sd',\n        'uvvt' => 'application/vnd.dece.ttml+xml',\n        'uvvu' => 'video/vnd.uvvu.mp4',\n        'uvvv' => 'video/vnd.dece.video',\n        'uvvx' => 'application/vnd.dece.unspecified',\n        'uvvz' => 'application/vnd.dece.zip',\n        'uvx' => 'application/vnd.dece.unspecified',\n        'uvz' => 'application/vnd.dece.zip',\n        'vbox' => 'application/x-virtualbox-vbox',\n        'vbox-extpack' => 'application/x-virtualbox-vbox-extpack',\n        'vcard' => 'text/vcard',\n        'vcd' => 'application/x-cdlink',\n        'vcf' => 'text/x-vcard',\n        'vcg' => 'application/vnd.groove-vcard',\n        'vcs' => 'text/x-vcalendar',\n        'vcx' => 'application/vnd.vcx',\n        'vdi' => 'application/x-virtualbox-vdi',\n        'vds' => 'model/vnd.sap.vds',\n        'vhd' => 'application/x-virtualbox-vhd',\n        'vis' => 'application/vnd.visionary',\n        'viv' => 'video/vnd.vivo',\n        'vlc' => 'application/videolan',\n        'vmdk' => 'application/x-virtualbox-vmdk',\n        'vob' => 'video/x-ms-vob',\n        'vor' => 'application/vnd.stardivision.writer',\n        'vox' => 'application/x-authorware-bin',\n        'vrml' => 'model/vrml',\n        'vsd' => 'application/vnd.visio',\n        'vsf' => 'application/vnd.vsf',\n        'vss' => 'application/vnd.visio',\n        'vst' => 'application/vnd.visio',\n        'vsw' => 'application/vnd.visio',\n        'vtf' => 'image/vnd.valve.source.texture',\n        'vtt' => 'text/vtt',\n        'vtu' => 'model/vnd.vtu',\n        'vxml' => 'application/voicexml+xml',\n        'w3d' => 'application/x-director',\n        'wad' => 'application/x-doom',\n        'wadl' => 'application/vnd.sun.wadl+xml',\n        'war' => 'application/java-archive',\n        'wasm' => 'application/wasm',\n        'wav' => 'audio/x-wav',\n        'wax' => 'audio/x-ms-wax',\n        'wbmp' => 'image/vnd.wap.wbmp',\n        'wbs' => 'application/vnd.criticaltools.wbs+xml',\n        'wbxml' => 'application/wbxml',\n        'wcm' => 'application/vnd.ms-works',\n        'wdb' => 'application/vnd.ms-works',\n        'wdp' => 'image/vnd.ms-photo',\n        'weba' => 'audio/webm',\n        'webapp' => 'application/x-web-app-manifest+json',\n        'webm' => 'video/webm',\n        'webmanifest' => 'application/manifest+json',\n        'webp' => 'image/webp',\n        'wg' => 'application/vnd.pmi.widget',\n        'wgt' => 'application/widget',\n        'wif' => 'application/watcherinfo+xml',\n        'wks' => 'application/vnd.ms-works',\n        'wm' => 'video/x-ms-wm',\n        'wma' => 'audio/x-ms-wma',\n        'wmd' => 'application/x-ms-wmd',\n        'wmf' => 'image/wmf',\n        'wml' => 'text/vnd.wap.wml',\n        'wmlc' => 'application/wmlc',\n        'wmls' => 'text/vnd.wap.wmlscript',\n        'wmlsc' => 'application/vnd.wap.wmlscriptc',\n        'wmv' => 'video/x-ms-wmv',\n        'wmx' => 'video/x-ms-wmx',\n        'wmz' => 'application/x-msmetafile',\n        'woff' => 'font/woff',\n        'woff2' => 'font/woff2',\n        'word' => 'application/msword',\n        'wpd' => 'application/vnd.wordperfect',\n        'wpl' => 'application/vnd.ms-wpl',\n        'wps' => 'application/vnd.ms-works',\n        'wqd' => 'application/vnd.wqd',\n        'wri' => 'application/x-mswrite',\n        'wrl' => 'model/vrml',\n        'wsc' => 'message/vnd.wfa.wsc',\n        'wsdl' => 'application/wsdl+xml',\n        'wspolicy' => 'application/wspolicy+xml',\n        'wtb' => 'application/vnd.webturbo',\n        'wvx' => 'video/x-ms-wvx',\n        'x3d' => 'model/x3d+xml',\n        'x3db' => 'model/x3d+fastinfoset',\n        'x3dbz' => 'model/x3d+binary',\n        'x3dv' => 'model/x3d-vrml',\n        'x3dvz' => 'model/x3d+vrml',\n        'x3dz' => 'model/x3d+xml',\n        'x32' => 'application/x-authorware-bin',\n        'x_b' => 'model/vnd.parasolid.transmit.binary',\n        'x_t' => 'model/vnd.parasolid.transmit.text',\n        'xaml' => 'application/xaml+xml',\n        'xap' => 'application/x-silverlight-app',\n        'xar' => 'application/vnd.xara',\n        'xav' => 'application/xcap-att+xml',\n        'xbap' => 'application/x-ms-xbap',\n        'xbd' => 'application/vnd.fujixerox.docuworks.binder',\n        'xbm' => 'image/x-xbitmap',\n        'xca' => 'application/xcap-caps+xml',\n        'xcs' => 'application/calendar+xml',\n        'xdf' => 'application/xcap-diff+xml',\n        'xdm' => 'application/vnd.syncml.dm+xml',\n        'xdp' => 'application/vnd.adobe.xdp+xml',\n        'xdssc' => 'application/dssc+xml',\n        'xdw' => 'application/vnd.fujixerox.docuworks',\n        'xel' => 'application/xcap-el+xml',\n        'xenc' => 'application/xenc+xml',\n        'xer' => 'application/patch-ops-error+xml',\n        'xfdf' => 'application/vnd.adobe.xfdf',\n        'xfdl' => 'application/vnd.xfdl',\n        'xht' => 'application/xhtml+xml',\n        'xhtml' => 'application/xhtml+xml',\n        'xhvml' => 'application/xv+xml',\n        'xif' => 'image/vnd.xiff',\n        'xl' => 'application/excel',\n        'xla' => 'application/vnd.ms-excel',\n        'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',\n        'xlc' => 'application/vnd.ms-excel',\n        'xlf' => 'application/xliff+xml',\n        'xlm' => 'application/vnd.ms-excel',\n        'xls' => 'application/vnd.ms-excel',\n        'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',\n        'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',\n        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n        'xlt' => 'application/vnd.ms-excel',\n        'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',\n        'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',\n        'xlw' => 'application/vnd.ms-excel',\n        'xm' => 'audio/xm',\n        'xml' => 'application/xml',\n        'xns' => 'application/xcap-ns+xml',\n        'xo' => 'application/vnd.olpc-sugar',\n        'xop' => 'application/xop+xml',\n        'xpi' => 'application/x-xpinstall',\n        'xpl' => 'application/xproc+xml',\n        'xpm' => 'image/x-xpixmap',\n        'xpr' => 'application/vnd.is-xpr',\n        'xps' => 'application/vnd.ms-xpsdocument',\n        'xpw' => 'application/vnd.intercon.formnet',\n        'xpx' => 'application/vnd.intercon.formnet',\n        'xsd' => 'application/xml',\n        'xsl' => 'application/xml',\n        'xslt' => 'application/xslt+xml',\n        'xsm' => 'application/vnd.syncml+xml',\n        'xspf' => 'application/xspf+xml',\n        'xul' => 'application/vnd.mozilla.xul+xml',\n        'xvm' => 'application/xv+xml',\n        'xvml' => 'application/xv+xml',\n        'xwd' => 'image/x-xwindowdump',\n        'xyz' => 'chemical/x-xyz',\n        'xz' => 'application/x-xz',\n        'yaml' => 'text/yaml',\n        'yang' => 'application/yang',\n        'yin' => 'application/yin+xml',\n        'yml' => 'text/yaml',\n        'ymp' => 'text/x-suse-ymp',\n        'z' => 'application/x-compress',\n        'z1' => 'application/x-zmachine',\n        'z2' => 'application/x-zmachine',\n        'z3' => 'application/x-zmachine',\n        'z4' => 'application/x-zmachine',\n        'z5' => 'application/x-zmachine',\n        'z6' => 'application/x-zmachine',\n        'z7' => 'application/x-zmachine',\n        'z8' => 'application/x-zmachine',\n        'zaz' => 'application/vnd.zzazz.deck+xml',\n        'zip' => 'application/zip',\n        'zir' => 'application/vnd.zul',\n        'zirz' => 'application/vnd.zul',\n        'zmm' => 'application/vnd.handheld-entertainment+xml',\n        'zsh' => 'text/x-scriptzsh',\n    ];\n\n    public function lookupMimeType(string $extension): ?string\n    {\n        return self::MIME_TYPES_FOR_EXTENSIONS[$extension] ?? null;\n    }\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/MimeTypeDetector.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace League\\MimeTypeDetection;\n\ninterface MimeTypeDetector\n{\n    /**\n     * @param string|resource $contents\n     */\n    public function detectMimeType(string $path, $contents): ?string;\n\n    public function detectMimeTypeFromBuffer(string $contents): ?string;\n\n    public function detectMimeTypeFromPath(string $path): ?string;\n\n    public function detectMimeTypeFromFile(string $path): ?string;\n}\n"
  },
  {
    "path": "vendor/league/mime-type-detection/src/OverridingExtensionToMimeTypeMap.php",
    "content": "<?php\n\nnamespace League\\MimeTypeDetection;\n\nclass OverridingExtensionToMimeTypeMap implements ExtensionToMimeTypeMap\n{\n    /**\n     * @var ExtensionToMimeTypeMap\n     */\n    private $innerMap;\n\n    /**\n     * @var string[]\n     */\n    private $overrides;\n\n    /**\n     * @param array<string, string>  $overrides\n     */\n    public function __construct(ExtensionToMimeTypeMap $innerMap, array $overrides)\n    {\n        $this->innerMap = $innerMap;\n        $this->overrides = $overrides;\n    }\n\n    public function lookupMimeType(string $extension): ?string\n    {\n        return $this->overrides[$extension] ?? $this->innerMap->lookupMimeType($extension);\n    }\n}\n"
  },
  {
    "path": "vendor/psr/cache/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file, in reverse chronological order by release.\n\n## 1.0.1 - 2016-08-06\n\n### Fixed\n\n- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr\n- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr\n- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell\n- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell\n\n## 1.0.0 - 2015-12-11\n\nInitial stable release; reflects accepted PSR-6 specification\n"
  },
  {
    "path": "vendor/psr/cache/LICENSE.txt",
    "content": "Copyright (c) 2015 PHP Framework Interoperability Group\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/psr/cache/README.md",
    "content": "Caching Interface\n==============\n\nThis repository holds all interfaces related to [PSR-6 (Caching Interface)][psr-url].\n\nNote that this is not a Caching implementation of its own. It is merely interfaces that describe the components of a Caching mechanism.\n\nThe installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.\n\n[psr-url]: https://www.php-fig.org/psr/psr-6/\n[package-url]: https://packagist.org/packages/psr/cache\n[implementation-url]: https://packagist.org/providers/psr/cache-implementation\n"
  },
  {
    "path": "vendor/psr/cache/composer.json",
    "content": "{\n    \"name\": \"psr/cache\",\n    \"description\": \"Common interface for caching libraries\",\n    \"keywords\": [\"psr\", \"psr-6\", \"cache\"],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"PHP-FIG\",\n            \"homepage\": \"https://www.php-fig.org/\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=8.0.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Psr\\\\Cache\\\\\": \"src/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.0.x-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/psr/cache/src/CacheException.php",
    "content": "<?php\n\nnamespace Psr\\Cache;\n\n/**\n * Exception interface for all exceptions thrown by an Implementing Library.\n */\ninterface CacheException extends \\Throwable\n{\n}\n"
  },
  {
    "path": "vendor/psr/cache/src/CacheItemInterface.php",
    "content": "<?php\n\nnamespace Psr\\Cache;\n\n/**\n * CacheItemInterface defines an interface for interacting with objects inside a cache.\n *\n * Each Item object MUST be associated with a specific key, which can be set\n * according to the implementing system and is typically passed by the\n * Cache\\CacheItemPoolInterface object.\n *\n * The Cache\\CacheItemInterface object encapsulates the storage and retrieval of\n * cache items. Each Cache\\CacheItemInterface is generated by a\n * Cache\\CacheItemPoolInterface object, which is responsible for any required\n * setup as well as associating the object with a unique Key.\n * Cache\\CacheItemInterface objects MUST be able to store and retrieve any type\n * of PHP value defined in the Data section of the specification.\n *\n * Calling Libraries MUST NOT instantiate Item objects themselves. They may only\n * be requested from a Pool object via the getItem() method.  Calling Libraries\n * SHOULD NOT assume that an Item created by one Implementing Library is\n * compatible with a Pool from another Implementing Library.\n */\ninterface CacheItemInterface\n{\n    /**\n     * Returns the key for the current cache item.\n     *\n     * The key is loaded by the Implementing Library, but should be available to\n     * the higher level callers when needed.\n     *\n     * @return string\n     *   The key string for this cache item.\n     */\n    public function getKey();\n\n    /**\n     * Retrieves the value of the item from the cache associated with this object's key.\n     *\n     * The value returned must be identical to the value originally stored by set().\n     *\n     * If isHit() returns false, this method MUST return null. Note that null\n     * is a legitimate cached value, so the isHit() method SHOULD be used to\n     * differentiate between \"null value was found\" and \"no value was found.\"\n     *\n     * @return mixed\n     *   The value corresponding to this cache item's key, or null if not found.\n     */\n    public function get();\n\n    /**\n     * Confirms if the cache item lookup resulted in a cache hit.\n     *\n     * Note: This method MUST NOT have a race condition between calling isHit()\n     * and calling get().\n     *\n     * @return bool\n     *   True if the request resulted in a cache hit. False otherwise.\n     */\n    public function isHit();\n\n    /**\n     * Sets the value represented by this cache item.\n     *\n     * The $value argument may be any item that can be serialized by PHP,\n     * although the method of serialization is left up to the Implementing\n     * Library.\n     *\n     * @param mixed $value\n     *   The serializable value to be stored.\n     *\n     * @return static\n     *   The invoked object.\n     */\n    public function set(mixed $value);\n\n    /**\n     * Sets the expiration time for this cache item.\n     *\n     * @param ?\\DateTimeInterface $expiration\n     *   The point in time after which the item MUST be considered expired.\n     *   If null is passed explicitly, a default value MAY be used. If none is set,\n     *   the value should be stored permanently or for as long as the\n     *   implementation allows.\n     *\n     * @return static\n     *   The called object.\n     */\n    public function expiresAt(?\\DateTimeInterface $expiration);\n\n    /**\n     * Sets the expiration time for this cache item.\n     *\n     * @param int|\\DateInterval|null $time\n     *   The period of time from the present after which the item MUST be considered\n     *   expired. An integer parameter is understood to be the time in seconds until\n     *   expiration. If null is passed explicitly, a default value MAY be used.\n     *   If none is set, the value should be stored permanently or for as long as the\n     *   implementation allows.\n     *\n     * @return static\n     *   The called object.\n     */\n    public function expiresAfter(int|\\DateInterval|null $time);\n}\n"
  },
  {
    "path": "vendor/psr/cache/src/CacheItemPoolInterface.php",
    "content": "<?php\n\nnamespace Psr\\Cache;\n\n/**\n * CacheItemPoolInterface generates CacheItemInterface objects.\n *\n * The primary purpose of Cache\\CacheItemPoolInterface is to accept a key from\n * the Calling Library and return the associated Cache\\CacheItemInterface object.\n * It is also the primary point of interaction with the entire cache collection.\n * All configuration and initialization of the Pool is left up to an\n * Implementing Library.\n */\ninterface CacheItemPoolInterface\n{\n    /**\n     * Returns a Cache Item representing the specified key.\n     *\n     * This method must always return a CacheItemInterface object, even in case of\n     * a cache miss. It MUST NOT return null.\n     *\n     * @param string $key\n     *   The key for which to return the corresponding Cache Item.\n     *\n     * @throws InvalidArgumentException\n     *   If the $key string is not a legal value a \\Psr\\Cache\\InvalidArgumentException\n     *   MUST be thrown.\n     *\n     * @return CacheItemInterface\n     *   The corresponding Cache Item.\n     */\n    public function getItem(string $key);\n\n    /**\n     * Returns a traversable set of cache items.\n     *\n     * @param string[] $keys\n     *   An indexed array of keys of items to retrieve.\n     *\n     * @throws InvalidArgumentException\n     *   If any of the keys in $keys are not a legal value a \\Psr\\Cache\\InvalidArgumentException\n     *   MUST be thrown.\n     *\n     * @return array|\\Traversable\n     *   A traversable collection of Cache Items keyed by the cache keys of\n     *   each item. A Cache item will be returned for each key, even if that\n     *   key is not found. However, if no keys are specified then an empty\n     *   traversable MUST be returned instead.\n     */\n    public function getItems(array $keys = []);\n\n    /**\n     * Confirms if the cache contains specified cache item.\n     *\n     * Note: This method MAY avoid retrieving the cached value for performance reasons.\n     * This could result in a race condition with CacheItemInterface::get(). To avoid\n     * such situation use CacheItemInterface::isHit() instead.\n     *\n     * @param string $key\n     *   The key for which to check existence.\n     *\n     * @throws InvalidArgumentException\n     *   If the $key string is not a legal value a \\Psr\\Cache\\InvalidArgumentException\n     *   MUST be thrown.\n     *\n     * @return bool\n     *   True if item exists in the cache, false otherwise.\n     */\n    public function hasItem(string $key);\n\n    /**\n     * Deletes all items in the pool.\n     *\n     * @return bool\n     *   True if the pool was successfully cleared. False if there was an error.\n     */\n    public function clear();\n\n    /**\n     * Removes the item from the pool.\n     *\n     * @param string $key\n     *   The key to delete.\n     *\n     * @throws InvalidArgumentException\n     *   If the $key string is not a legal value a \\Psr\\Cache\\InvalidArgumentException\n     *   MUST be thrown.\n     *\n     * @return bool\n     *   True if the item was successfully removed. False if there was an error.\n     */\n    public function deleteItem(string $key);\n\n    /**\n     * Removes multiple items from the pool.\n     *\n     * @param string[] $keys\n     *   An array of keys that should be removed from the pool.\n     *\n     * @throws InvalidArgumentException\n     *   If any of the keys in $keys are not a legal value a \\Psr\\Cache\\InvalidArgumentException\n     *   MUST be thrown.\n     *\n     * @return bool\n     *   True if the items were successfully removed. False if there was an error.\n     */\n    public function deleteItems(array $keys);\n\n    /**\n     * Persists a cache item immediately.\n     *\n     * @param CacheItemInterface $item\n     *   The cache item to save.\n     *\n     * @return bool\n     *   True if the item was successfully persisted. False if there was an error.\n     */\n    public function save(CacheItemInterface $item);\n\n    /**\n     * Sets a cache item to be persisted later.\n     *\n     * @param CacheItemInterface $item\n     *   The cache item to save.\n     *\n     * @return bool\n     *   False if the item could not be queued or if a commit was attempted and failed. True otherwise.\n     */\n    public function saveDeferred(CacheItemInterface $item);\n\n    /**\n     * Persists any deferred cache items.\n     *\n     * @return bool\n     *   True if all not-yet-saved items were successfully saved or there were none. False otherwise.\n     */\n    public function commit();\n}\n"
  },
  {
    "path": "vendor/psr/cache/src/InvalidArgumentException.php",
    "content": "<?php\n\nnamespace Psr\\Cache;\n\n/**\n * Exception interface for invalid cache arguments.\n *\n * Any time an invalid argument is passed into a method it must throw an\n * exception class which implements Psr\\Cache\\InvalidArgumentException.\n */\ninterface InvalidArgumentException extends CacheException\n{\n}\n"
  },
  {
    "path": "vendor/psr/http-client/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file, in reverse chronological order by release.\n\n## 1.0.1\n\nAllow installation with PHP 8. No code changes.\n\n## 1.0.0\n\nFirst stable release. No changes since 0.3.0.\n\n## 0.3.0\n\nAdded Interface suffix on exceptions\n \n## 0.2.0 \n\nAll exceptions are in `Psr\\Http\\Client` namespace\n\n## 0.1.0\n\nFirst release\n"
  },
  {
    "path": "vendor/psr/http-client/LICENSE",
    "content": "Copyright (c) 2017 PHP Framework Interoperability Group\n\nPermission is hereby granted, free of charge, to any person obtaining a copy \nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights \nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is \nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in \nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/psr/http-client/README.md",
    "content": "HTTP Client\n===========\n\nThis repository holds all the common code related to [PSR-18 (HTTP Client)][psr-url].\n\nNote that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client.\n\nThe installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.\n\n[psr-url]: http://www.php-fig.org/psr/psr-18\n[package-url]: https://packagist.org/packages/psr/http-client\n[implementation-url]: https://packagist.org/providers/psr/http-client-implementation\n"
  },
  {
    "path": "vendor/psr/http-client/composer.json",
    "content": "{\n    \"name\": \"psr/http-client\",\n    \"description\": \"Common interface for HTTP clients\",\n    \"keywords\": [\"psr\", \"psr-18\", \"http\", \"http-client\"],\n    \"homepage\": \"https://github.com/php-fig/http-client\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"PHP-FIG\",\n            \"homepage\": \"http://www.php-fig.org/\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^7.0 || ^8.0\",\n        \"psr/http-message\": \"^1.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Psr\\\\Http\\\\Client\\\\\": \"src/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.0.x-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/psr/http-client/src/ClientExceptionInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Client;\n\n/**\n * Every HTTP client related exception MUST implement this interface.\n */\ninterface ClientExceptionInterface extends \\Throwable\n{\n}\n"
  },
  {
    "path": "vendor/psr/http-client/src/ClientInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Client;\n\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\n\ninterface ClientInterface\n{\n    /**\n     * Sends a PSR-7 request and returns a PSR-7 response.\n     *\n     * @param RequestInterface $request\n     *\n     * @return ResponseInterface\n     *\n     * @throws \\Psr\\Http\\Client\\ClientExceptionInterface If an error happens while processing the request.\n     */\n    public function sendRequest(RequestInterface $request): ResponseInterface;\n}\n"
  },
  {
    "path": "vendor/psr/http-client/src/NetworkExceptionInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Client;\n\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Thrown when the request cannot be completed because of network issues.\n *\n * There is no response object as this exception is thrown when no response has been received.\n *\n * Example: the target host name can not be resolved or the connection failed.\n */\ninterface NetworkExceptionInterface extends ClientExceptionInterface\n{\n    /**\n     * Returns the request.\n     *\n     * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()\n     *\n     * @return RequestInterface\n     */\n    public function getRequest(): RequestInterface;\n}\n"
  },
  {
    "path": "vendor/psr/http-client/src/RequestExceptionInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Client;\n\nuse Psr\\Http\\Message\\RequestInterface;\n\n/**\n * Exception for when a request failed.\n *\n * Examples:\n *      - Request is invalid (e.g. method is missing)\n *      - Runtime request errors (e.g. the body stream is not seekable)\n */\ninterface RequestExceptionInterface extends ClientExceptionInterface\n{\n    /**\n     * Returns the request.\n     *\n     * The request object MAY be a different object from the one passed to ClientInterface::sendRequest()\n     *\n     * @return RequestInterface\n     */\n    public function getRequest(): RequestInterface;\n}\n"
  },
  {
    "path": "vendor/psr/http-message/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file, in reverse chronological order by release.\n\n## 1.0.1 - 2016-08-06\n\n### Added\n\n- Nothing.\n\n### Deprecated\n\n- Nothing.\n\n### Removed\n\n- Nothing.\n\n### Fixed\n\n- Updated all `@return self` annotation references in interfaces to use\n  `@return static`, which more closelly follows the semantics of the\n  specification.\n- Updated the `MessageInterface::getHeaders()` return annotation to use the\n  value `string[][]`, indicating the format is a nested array of strings.\n- Updated the `@link` annotation for `RequestInterface::withRequestTarget()`\n  to point to the correct section of RFC 7230.\n- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation\n  to add the parameter name (`$uploadedFiles`).\n- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()`\n  method to correctly reference the method parameter (it was referencing an\n  incorrect parameter name previously).\n\n## 1.0.0 - 2016-05-18\n\nInitial stable release; reflects accepted PSR-7 specification.\n"
  },
  {
    "path": "vendor/psr/http-message/LICENSE",
    "content": "Copyright (c) 2014 PHP Framework Interoperability Group\n\nPermission is hereby granted, free of charge, to any person obtaining a copy \nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights \nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is \nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in \nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/psr/http-message/README.md",
    "content": "PSR Http Message\n================\n\nThis repository holds all interfaces/classes/traits related to\n[PSR-7](http://www.php-fig.org/psr/psr-7/).\n\nNote that this is not a HTTP message implementation of its own. It is merely an\ninterface that describes a HTTP message. See the specification for more details.\n\nUsage\n-----\n\nWe'll certainly need some stuff in here."
  },
  {
    "path": "vendor/psr/http-message/composer.json",
    "content": "{\n    \"name\": \"psr/http-message\",\n    \"description\": \"Common interface for HTTP messages\",\n    \"keywords\": [\"psr\", \"psr-7\", \"http\", \"http-message\", \"request\", \"response\"],\n    \"homepage\": \"https://github.com/php-fig/http-message\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"PHP-FIG\",\n            \"homepage\": \"http://www.php-fig.org/\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=5.3.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Psr\\\\Http\\\\Message\\\\\": \"src/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.0.x-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/MessageInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Message;\n\n/**\n * HTTP messages consist of requests from a client to a server and responses\n * from a server to a client. This interface defines the methods common to\n * each.\n *\n * Messages are considered immutable; all methods that might change state MUST\n * be implemented such that they retain the internal state of the current\n * message and return an instance that contains the changed state.\n *\n * @link http://www.ietf.org/rfc/rfc7230.txt\n * @link http://www.ietf.org/rfc/rfc7231.txt\n */\ninterface MessageInterface\n{\n    /**\n     * Retrieves the HTTP protocol version as a string.\n     *\n     * The string MUST contain only the HTTP version number (e.g., \"1.1\", \"1.0\").\n     *\n     * @return string HTTP protocol version.\n     */\n    public function getProtocolVersion();\n\n    /**\n     * Return an instance with the specified HTTP protocol version.\n     *\n     * The version string MUST contain only the HTTP version number (e.g.,\n     * \"1.1\", \"1.0\").\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * new protocol version.\n     *\n     * @param string $version HTTP protocol version\n     * @return static\n     */\n    public function withProtocolVersion($version);\n\n    /**\n     * Retrieves all message header values.\n     *\n     * The keys represent the header name as it will be sent over the wire, and\n     * each value is an array of strings associated with the header.\n     *\n     *     // Represent the headers as a string\n     *     foreach ($message->getHeaders() as $name => $values) {\n     *         echo $name . \": \" . implode(\", \", $values);\n     *     }\n     *\n     *     // Emit headers iteratively:\n     *     foreach ($message->getHeaders() as $name => $values) {\n     *         foreach ($values as $value) {\n     *             header(sprintf('%s: %s', $name, $value), false);\n     *         }\n     *     }\n     *\n     * While header names are not case-sensitive, getHeaders() will preserve the\n     * exact case in which headers were originally specified.\n     *\n     * @return string[][] Returns an associative array of the message's headers. Each\n     *     key MUST be a header name, and each value MUST be an array of strings\n     *     for that header.\n     */\n    public function getHeaders();\n\n    /**\n     * Checks if a header exists by the given case-insensitive name.\n     *\n     * @param string $name Case-insensitive header field name.\n     * @return bool Returns true if any header names match the given header\n     *     name using a case-insensitive string comparison. Returns false if\n     *     no matching header name is found in the message.\n     */\n    public function hasHeader($name);\n\n    /**\n     * Retrieves a message header value by the given case-insensitive name.\n     *\n     * This method returns an array of all the header values of the given\n     * case-insensitive header name.\n     *\n     * If the header does not appear in the message, this method MUST return an\n     * empty array.\n     *\n     * @param string $name Case-insensitive header field name.\n     * @return string[] An array of string values as provided for the given\n     *    header. If the header does not appear in the message, this method MUST\n     *    return an empty array.\n     */\n    public function getHeader($name);\n\n    /**\n     * Retrieves a comma-separated string of the values for a single header.\n     *\n     * This method returns all of the header values of the given\n     * case-insensitive header name as a string concatenated together using\n     * a comma.\n     *\n     * NOTE: Not all header values may be appropriately represented using\n     * comma concatenation. For such headers, use getHeader() instead\n     * and supply your own delimiter when concatenating.\n     *\n     * If the header does not appear in the message, this method MUST return\n     * an empty string.\n     *\n     * @param string $name Case-insensitive header field name.\n     * @return string A string of values as provided for the given header\n     *    concatenated together using a comma. If the header does not appear in\n     *    the message, this method MUST return an empty string.\n     */\n    public function getHeaderLine($name);\n\n    /**\n     * Return an instance with the provided value replacing the specified header.\n     *\n     * While header names are case-insensitive, the casing of the header will\n     * be preserved by this function, and returned from getHeaders().\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * new and/or updated header and value.\n     *\n     * @param string $name Case-insensitive header field name.\n     * @param string|string[] $value Header value(s).\n     * @return static\n     * @throws \\InvalidArgumentException for invalid header names or values.\n     */\n    public function withHeader($name, $value);\n\n    /**\n     * Return an instance with the specified header appended with the given value.\n     *\n     * Existing values for the specified header will be maintained. The new\n     * value(s) will be appended to the existing list. If the header did not\n     * exist previously, it will be added.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * new header and/or value.\n     *\n     * @param string $name Case-insensitive header field name to add.\n     * @param string|string[] $value Header value(s).\n     * @return static\n     * @throws \\InvalidArgumentException for invalid header names or values.\n     */\n    public function withAddedHeader($name, $value);\n\n    /**\n     * Return an instance without the specified header.\n     *\n     * Header resolution MUST be done without case-sensitivity.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that removes\n     * the named header.\n     *\n     * @param string $name Case-insensitive header field name to remove.\n     * @return static\n     */\n    public function withoutHeader($name);\n\n    /**\n     * Gets the body of the message.\n     *\n     * @return StreamInterface Returns the body as a stream.\n     */\n    public function getBody();\n\n    /**\n     * Return an instance with the specified message body.\n     *\n     * The body MUST be a StreamInterface object.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return a new instance that has the\n     * new body stream.\n     *\n     * @param StreamInterface $body Body.\n     * @return static\n     * @throws \\InvalidArgumentException When the body is not valid.\n     */\n    public function withBody(StreamInterface $body);\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/RequestInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Message;\n\n/**\n * Representation of an outgoing, client-side request.\n *\n * Per the HTTP specification, this interface includes properties for\n * each of the following:\n *\n * - Protocol version\n * - HTTP method\n * - URI\n * - Headers\n * - Message body\n *\n * During construction, implementations MUST attempt to set the Host header from\n * a provided URI if no Host header is provided.\n *\n * Requests are considered immutable; all methods that might change state MUST\n * be implemented such that they retain the internal state of the current\n * message and return an instance that contains the changed state.\n */\ninterface RequestInterface extends MessageInterface\n{\n    /**\n     * Retrieves the message's request target.\n     *\n     * Retrieves the message's request-target either as it will appear (for\n     * clients), as it appeared at request (for servers), or as it was\n     * specified for the instance (see withRequestTarget()).\n     *\n     * In most cases, this will be the origin-form of the composed URI,\n     * unless a value was provided to the concrete implementation (see\n     * withRequestTarget() below).\n     *\n     * If no URI is available, and no request-target has been specifically\n     * provided, this method MUST return the string \"/\".\n     *\n     * @return string\n     */\n    public function getRequestTarget();\n\n    /**\n     * Return an instance with the specific request-target.\n     *\n     * If the request needs a non-origin-form request-target — e.g., for\n     * specifying an absolute-form, authority-form, or asterisk-form —\n     * this method may be used to create an instance with the specified\n     * request-target, verbatim.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * changed request target.\n     *\n     * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various\n     *     request-target forms allowed in request messages)\n     * @param mixed $requestTarget\n     * @return static\n     */\n    public function withRequestTarget($requestTarget);\n\n    /**\n     * Retrieves the HTTP method of the request.\n     *\n     * @return string Returns the request method.\n     */\n    public function getMethod();\n\n    /**\n     * Return an instance with the provided HTTP method.\n     *\n     * While HTTP method names are typically all uppercase characters, HTTP\n     * method names are case-sensitive and thus implementations SHOULD NOT\n     * modify the given string.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * changed request method.\n     *\n     * @param string $method Case-sensitive method.\n     * @return static\n     * @throws \\InvalidArgumentException for invalid HTTP methods.\n     */\n    public function withMethod($method);\n\n    /**\n     * Retrieves the URI instance.\n     *\n     * This method MUST return a UriInterface instance.\n     *\n     * @link http://tools.ietf.org/html/rfc3986#section-4.3\n     * @return UriInterface Returns a UriInterface instance\n     *     representing the URI of the request.\n     */\n    public function getUri();\n\n    /**\n     * Returns an instance with the provided URI.\n     *\n     * This method MUST update the Host header of the returned request by\n     * default if the URI contains a host component. If the URI does not\n     * contain a host component, any pre-existing Host header MUST be carried\n     * over to the returned request.\n     *\n     * You can opt-in to preserving the original state of the Host header by\n     * setting `$preserveHost` to `true`. When `$preserveHost` is set to\n     * `true`, this method interacts with the Host header in the following ways:\n     *\n     * - If the Host header is missing or empty, and the new URI contains\n     *   a host component, this method MUST update the Host header in the returned\n     *   request.\n     * - If the Host header is missing or empty, and the new URI does not contain a\n     *   host component, this method MUST NOT update the Host header in the returned\n     *   request.\n     * - If a Host header is present and non-empty, this method MUST NOT update\n     *   the Host header in the returned request.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * new UriInterface instance.\n     *\n     * @link http://tools.ietf.org/html/rfc3986#section-4.3\n     * @param UriInterface $uri New request URI to use.\n     * @param bool $preserveHost Preserve the original state of the Host header.\n     * @return static\n     */\n    public function withUri(UriInterface $uri, $preserveHost = false);\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/ResponseInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Message;\n\n/**\n * Representation of an outgoing, server-side response.\n *\n * Per the HTTP specification, this interface includes properties for\n * each of the following:\n *\n * - Protocol version\n * - Status code and reason phrase\n * - Headers\n * - Message body\n *\n * Responses are considered immutable; all methods that might change state MUST\n * be implemented such that they retain the internal state of the current\n * message and return an instance that contains the changed state.\n */\ninterface ResponseInterface extends MessageInterface\n{\n    /**\n     * Gets the response status code.\n     *\n     * The status code is a 3-digit integer result code of the server's attempt\n     * to understand and satisfy the request.\n     *\n     * @return int Status code.\n     */\n    public function getStatusCode();\n\n    /**\n     * Return an instance with the specified status code and, optionally, reason phrase.\n     *\n     * If no reason phrase is specified, implementations MAY choose to default\n     * to the RFC 7231 or IANA recommended reason phrase for the response's\n     * status code.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * updated status and reason phrase.\n     *\n     * @link http://tools.ietf.org/html/rfc7231#section-6\n     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml\n     * @param int $code The 3-digit integer result code to set.\n     * @param string $reasonPhrase The reason phrase to use with the\n     *     provided status code; if none is provided, implementations MAY\n     *     use the defaults as suggested in the HTTP specification.\n     * @return static\n     * @throws \\InvalidArgumentException For invalid status code arguments.\n     */\n    public function withStatus($code, $reasonPhrase = '');\n\n    /**\n     * Gets the response reason phrase associated with the status code.\n     *\n     * Because a reason phrase is not a required element in a response\n     * status line, the reason phrase value MAY be null. Implementations MAY\n     * choose to return the default RFC 7231 recommended reason phrase (or those\n     * listed in the IANA HTTP Status Code Registry) for the response's\n     * status code.\n     *\n     * @link http://tools.ietf.org/html/rfc7231#section-6\n     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml\n     * @return string Reason phrase; must return an empty string if none present.\n     */\n    public function getReasonPhrase();\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/ServerRequestInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Message;\n\n/**\n * Representation of an incoming, server-side HTTP request.\n *\n * Per the HTTP specification, this interface includes properties for\n * each of the following:\n *\n * - Protocol version\n * - HTTP method\n * - URI\n * - Headers\n * - Message body\n *\n * Additionally, it encapsulates all data as it has arrived to the\n * application from the CGI and/or PHP environment, including:\n *\n * - The values represented in $_SERVER.\n * - Any cookies provided (generally via $_COOKIE)\n * - Query string arguments (generally via $_GET, or as parsed via parse_str())\n * - Upload files, if any (as represented by $_FILES)\n * - Deserialized body parameters (generally from $_POST)\n *\n * $_SERVER values MUST be treated as immutable, as they represent application\n * state at the time of request; as such, no methods are provided to allow\n * modification of those values. The other values provide such methods, as they\n * can be restored from $_SERVER or the request body, and may need treatment\n * during the application (e.g., body parameters may be deserialized based on\n * content type).\n *\n * Additionally, this interface recognizes the utility of introspecting a\n * request to derive and match additional parameters (e.g., via URI path\n * matching, decrypting cookie values, deserializing non-form-encoded body\n * content, matching authorization headers to users, etc). These parameters\n * are stored in an \"attributes\" property.\n *\n * Requests are considered immutable; all methods that might change state MUST\n * be implemented such that they retain the internal state of the current\n * message and return an instance that contains the changed state.\n */\ninterface ServerRequestInterface extends RequestInterface\n{\n    /**\n     * Retrieve server parameters.\n     *\n     * Retrieves data related to the incoming request environment,\n     * typically derived from PHP's $_SERVER superglobal. The data IS NOT\n     * REQUIRED to originate from $_SERVER.\n     *\n     * @return array\n     */\n    public function getServerParams();\n\n    /**\n     * Retrieve cookies.\n     *\n     * Retrieves cookies sent by the client to the server.\n     *\n     * The data MUST be compatible with the structure of the $_COOKIE\n     * superglobal.\n     *\n     * @return array\n     */\n    public function getCookieParams();\n\n    /**\n     * Return an instance with the specified cookies.\n     *\n     * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST\n     * be compatible with the structure of $_COOKIE. Typically, this data will\n     * be injected at instantiation.\n     *\n     * This method MUST NOT update the related Cookie header of the request\n     * instance, nor related values in the server params.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * updated cookie values.\n     *\n     * @param array $cookies Array of key/value pairs representing cookies.\n     * @return static\n     */\n    public function withCookieParams(array $cookies);\n\n    /**\n     * Retrieve query string arguments.\n     *\n     * Retrieves the deserialized query string arguments, if any.\n     *\n     * Note: the query params might not be in sync with the URI or server\n     * params. If you need to ensure you are only getting the original\n     * values, you may need to parse the query string from `getUri()->getQuery()`\n     * or from the `QUERY_STRING` server param.\n     *\n     * @return array\n     */\n    public function getQueryParams();\n\n    /**\n     * Return an instance with the specified query string arguments.\n     *\n     * These values SHOULD remain immutable over the course of the incoming\n     * request. They MAY be injected during instantiation, such as from PHP's\n     * $_GET superglobal, or MAY be derived from some other value such as the\n     * URI. In cases where the arguments are parsed from the URI, the data\n     * MUST be compatible with what PHP's parse_str() would return for\n     * purposes of how duplicate query parameters are handled, and how nested\n     * sets are handled.\n     *\n     * Setting query string arguments MUST NOT change the URI stored by the\n     * request, nor the values in the server params.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * updated query string arguments.\n     *\n     * @param array $query Array of query string arguments, typically from\n     *     $_GET.\n     * @return static\n     */\n    public function withQueryParams(array $query);\n\n    /**\n     * Retrieve normalized file upload data.\n     *\n     * This method returns upload metadata in a normalized tree, with each leaf\n     * an instance of Psr\\Http\\Message\\UploadedFileInterface.\n     *\n     * These values MAY be prepared from $_FILES or the message body during\n     * instantiation, or MAY be injected via withUploadedFiles().\n     *\n     * @return array An array tree of UploadedFileInterface instances; an empty\n     *     array MUST be returned if no data is present.\n     */\n    public function getUploadedFiles();\n\n    /**\n     * Create a new instance with the specified uploaded files.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * updated body parameters.\n     *\n     * @param array $uploadedFiles An array tree of UploadedFileInterface instances.\n     * @return static\n     * @throws \\InvalidArgumentException if an invalid structure is provided.\n     */\n    public function withUploadedFiles(array $uploadedFiles);\n\n    /**\n     * Retrieve any parameters provided in the request body.\n     *\n     * If the request Content-Type is either application/x-www-form-urlencoded\n     * or multipart/form-data, and the request method is POST, this method MUST\n     * return the contents of $_POST.\n     *\n     * Otherwise, this method may return any results of deserializing\n     * the request body content; as parsing returns structured content, the\n     * potential types MUST be arrays or objects only. A null value indicates\n     * the absence of body content.\n     *\n     * @return null|array|object The deserialized body parameters, if any.\n     *     These will typically be an array or object.\n     */\n    public function getParsedBody();\n\n    /**\n     * Return an instance with the specified body parameters.\n     *\n     * These MAY be injected during instantiation.\n     *\n     * If the request Content-Type is either application/x-www-form-urlencoded\n     * or multipart/form-data, and the request method is POST, use this method\n     * ONLY to inject the contents of $_POST.\n     *\n     * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of\n     * deserializing the request body content. Deserialization/parsing returns\n     * structured data, and, as such, this method ONLY accepts arrays or objects,\n     * or a null value if nothing was available to parse.\n     *\n     * As an example, if content negotiation determines that the request data\n     * is a JSON payload, this method could be used to create a request\n     * instance with the deserialized parameters.\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * updated body parameters.\n     *\n     * @param null|array|object $data The deserialized body data. This will\n     *     typically be in an array or object.\n     * @return static\n     * @throws \\InvalidArgumentException if an unsupported argument type is\n     *     provided.\n     */\n    public function withParsedBody($data);\n\n    /**\n     * Retrieve attributes derived from the request.\n     *\n     * The request \"attributes\" may be used to allow injection of any\n     * parameters derived from the request: e.g., the results of path\n     * match operations; the results of decrypting cookies; the results of\n     * deserializing non-form-encoded message bodies; etc. Attributes\n     * will be application and request specific, and CAN be mutable.\n     *\n     * @return array Attributes derived from the request.\n     */\n    public function getAttributes();\n\n    /**\n     * Retrieve a single derived request attribute.\n     *\n     * Retrieves a single derived request attribute as described in\n     * getAttributes(). If the attribute has not been previously set, returns\n     * the default value as provided.\n     *\n     * This method obviates the need for a hasAttribute() method, as it allows\n     * specifying a default value to return if the attribute is not found.\n     *\n     * @see getAttributes()\n     * @param string $name The attribute name.\n     * @param mixed $default Default value to return if the attribute does not exist.\n     * @return mixed\n     */\n    public function getAttribute($name, $default = null);\n\n    /**\n     * Return an instance with the specified derived request attribute.\n     *\n     * This method allows setting a single derived request attribute as\n     * described in getAttributes().\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that has the\n     * updated attribute.\n     *\n     * @see getAttributes()\n     * @param string $name The attribute name.\n     * @param mixed $value The value of the attribute.\n     * @return static\n     */\n    public function withAttribute($name, $value);\n\n    /**\n     * Return an instance that removes the specified derived request attribute.\n     *\n     * This method allows removing a single derived request attribute as\n     * described in getAttributes().\n     *\n     * This method MUST be implemented in such a way as to retain the\n     * immutability of the message, and MUST return an instance that removes\n     * the attribute.\n     *\n     * @see getAttributes()\n     * @param string $name The attribute name.\n     * @return static\n     */\n    public function withoutAttribute($name);\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/StreamInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Message;\n\n/**\n * Describes a data stream.\n *\n * Typically, an instance will wrap a PHP stream; this interface provides\n * a wrapper around the most common operations, including serialization of\n * the entire stream to a string.\n */\ninterface StreamInterface\n{\n    /**\n     * Reads all data from the stream into a string, from the beginning to end.\n     *\n     * This method MUST attempt to seek to the beginning of the stream before\n     * reading data and read the stream until the end is reached.\n     *\n     * Warning: This could attempt to load a large amount of data into memory.\n     *\n     * This method MUST NOT raise an exception in order to conform with PHP's\n     * string casting operations.\n     *\n     * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring\n     * @return string\n     */\n    public function __toString();\n\n    /**\n     * Closes the stream and any underlying resources.\n     *\n     * @return void\n     */\n    public function close();\n\n    /**\n     * Separates any underlying resources from the stream.\n     *\n     * After the stream has been detached, the stream is in an unusable state.\n     *\n     * @return resource|null Underlying PHP stream, if any\n     */\n    public function detach();\n\n    /**\n     * Get the size of the stream if known.\n     *\n     * @return int|null Returns the size in bytes if known, or null if unknown.\n     */\n    public function getSize();\n\n    /**\n     * Returns the current position of the file read/write pointer\n     *\n     * @return int Position of the file pointer\n     * @throws \\RuntimeException on error.\n     */\n    public function tell();\n\n    /**\n     * Returns true if the stream is at the end of the stream.\n     *\n     * @return bool\n     */\n    public function eof();\n\n    /**\n     * Returns whether or not the stream is seekable.\n     *\n     * @return bool\n     */\n    public function isSeekable();\n\n    /**\n     * Seek to a position in the stream.\n     *\n     * @link http://www.php.net/manual/en/function.fseek.php\n     * @param int $offset Stream offset\n     * @param int $whence Specifies how the cursor position will be calculated\n     *     based on the seek offset. Valid values are identical to the built-in\n     *     PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to\n     *     offset bytes SEEK_CUR: Set position to current location plus offset\n     *     SEEK_END: Set position to end-of-stream plus offset.\n     * @throws \\RuntimeException on failure.\n     */\n    public function seek($offset, $whence = SEEK_SET);\n\n    /**\n     * Seek to the beginning of the stream.\n     *\n     * If the stream is not seekable, this method will raise an exception;\n     * otherwise, it will perform a seek(0).\n     *\n     * @see seek()\n     * @link http://www.php.net/manual/en/function.fseek.php\n     * @throws \\RuntimeException on failure.\n     */\n    public function rewind();\n\n    /**\n     * Returns whether or not the stream is writable.\n     *\n     * @return bool\n     */\n    public function isWritable();\n\n    /**\n     * Write data to the stream.\n     *\n     * @param string $string The string that is to be written.\n     * @return int Returns the number of bytes written to the stream.\n     * @throws \\RuntimeException on failure.\n     */\n    public function write($string);\n\n    /**\n     * Returns whether or not the stream is readable.\n     *\n     * @return bool\n     */\n    public function isReadable();\n\n    /**\n     * Read data from the stream.\n     *\n     * @param int $length Read up to $length bytes from the object and return\n     *     them. Fewer than $length bytes may be returned if underlying stream\n     *     call returns fewer bytes.\n     * @return string Returns the data read from the stream, or an empty string\n     *     if no bytes are available.\n     * @throws \\RuntimeException if an error occurs.\n     */\n    public function read($length);\n\n    /**\n     * Returns the remaining contents in a string\n     *\n     * @return string\n     * @throws \\RuntimeException if unable to read or an error occurs while\n     *     reading.\n     */\n    public function getContents();\n\n    /**\n     * Get stream metadata as an associative array or retrieve a specific key.\n     *\n     * The keys returned are identical to the keys returned from PHP's\n     * stream_get_meta_data() function.\n     *\n     * @link http://php.net/manual/en/function.stream-get-meta-data.php\n     * @param string $key Specific metadata to retrieve.\n     * @return array|mixed|null Returns an associative array if no key is\n     *     provided. Returns a specific key value if a key is provided and the\n     *     value is found, or null if the key is not found.\n     */\n    public function getMetadata($key = null);\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/UploadedFileInterface.php",
    "content": "<?php\n\nnamespace Psr\\Http\\Message;\n\n/**\n * Value object representing a file uploaded through an HTTP request.\n *\n * Instances of this interface are considered immutable; all methods that\n * might change state MUST be implemented such that they retain the internal\n * state of the current instance and return an instance that contains the\n * changed state.\n */\ninterface UploadedFileInterface\n{\n    /**\n     * Retrieve a stream representing the uploaded file.\n     *\n     * This method MUST return a StreamInterface instance, representing the\n     * uploaded file. The purpose of this method is to allow utilizing native PHP\n     * stream functionality to manipulate the file upload, such as\n     * stream_copy_to_stream() (though the result will need to be decorated in a\n     * native PHP stream wrapper to work with such functions).\n     *\n     * If the moveTo() method has been called previously, this method MUST raise\n     * an exception.\n     *\n     * @return StreamInterface Stream representation of the uploaded file.\n     * @throws \\RuntimeException in cases when no stream is available or can be\n     *     created.\n     */\n    public function getStream();\n\n    /**\n     * Move the uploaded file to a new location.\n     *\n     * Use this method as an alternative to move_uploaded_file(). This method is\n     * guaranteed to work in both SAPI and non-SAPI environments.\n     * Implementations must determine which environment they are in, and use the\n     * appropriate method (move_uploaded_file(), rename(), or a stream\n     * operation) to perform the operation.\n     *\n     * $targetPath may be an absolute path, or a relative path. If it is a\n     * relative path, resolution should be the same as used by PHP's rename()\n     * function.\n     *\n     * The original file or stream MUST be removed on completion.\n     *\n     * If this method is called more than once, any subsequent calls MUST raise\n     * an exception.\n     *\n     * When used in an SAPI environment where $_FILES is populated, when writing\n     * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be\n     * used to ensure permissions and upload status are verified correctly.\n     *\n     * If you wish to move to a stream, use getStream(), as SAPI operations\n     * cannot guarantee writing to stream destinations.\n     *\n     * @see http://php.net/is_uploaded_file\n     * @see http://php.net/move_uploaded_file\n     * @param string $targetPath Path to which to move the uploaded file.\n     * @throws \\InvalidArgumentException if the $targetPath specified is invalid.\n     * @throws \\RuntimeException on any error during the move operation, or on\n     *     the second or subsequent call to the method.\n     */\n    public function moveTo($targetPath);\n    \n    /**\n     * Retrieve the file size.\n     *\n     * Implementations SHOULD return the value stored in the \"size\" key of\n     * the file in the $_FILES array if available, as PHP calculates this based\n     * on the actual size transmitted.\n     *\n     * @return int|null The file size in bytes or null if unknown.\n     */\n    public function getSize();\n    \n    /**\n     * Retrieve the error associated with the uploaded file.\n     *\n     * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.\n     *\n     * If the file was uploaded successfully, this method MUST return\n     * UPLOAD_ERR_OK.\n     *\n     * Implementations SHOULD return the value stored in the \"error\" key of\n     * the file in the $_FILES array.\n     *\n     * @see http://php.net/manual/en/features.file-upload.errors.php\n     * @return int One of PHP's UPLOAD_ERR_XXX constants.\n     */\n    public function getError();\n    \n    /**\n     * Retrieve the filename sent by the client.\n     *\n     * Do not trust the value returned by this method. A client could send\n     * a malicious filename with the intention to corrupt or hack your\n     * application.\n     *\n     * Implementations SHOULD return the value stored in the \"name\" key of\n     * the file in the $_FILES array.\n     *\n     * @return string|null The filename sent by the client or null if none\n     *     was provided.\n     */\n    public function getClientFilename();\n    \n    /**\n     * Retrieve the media type sent by the client.\n     *\n     * Do not trust the value returned by this method. A client could send\n     * a malicious media type with the intention to corrupt or hack your\n     * application.\n     *\n     * Implementations SHOULD return the value stored in the \"type\" key of\n     * the file in the $_FILES array.\n     *\n     * @return string|null The media type sent by the client or null if none\n     *     was provided.\n     */\n    public function getClientMediaType();\n}\n"
  },
  {
    "path": "vendor/psr/http-message/src/UriInterface.php",
    "content": "<?php\nnamespace Psr\\Http\\Message;\n\n/**\n * Value object representing a URI.\n *\n * This interface is meant to represent URIs according to RFC 3986 and to\n * provide methods for most common operations. Additional functionality for\n * working with URIs can be provided on top of the interface or externally.\n * Its primary use is for HTTP requests, but may also be used in other\n * contexts.\n *\n * Instances of this interface are considered immutable; all methods that\n * might change state MUST be implemented such that they retain the internal\n * state of the current instance and return an instance that contains the\n * changed state.\n *\n * Typically the Host header will be also be present in the request message.\n * For server-side requests, the scheme will typically be discoverable in the\n * server parameters.\n *\n * @link http://tools.ietf.org/html/rfc3986 (the URI specification)\n */\ninterface UriInterface\n{\n    /**\n     * Retrieve the scheme component of the URI.\n     *\n     * If no scheme is present, this method MUST return an empty string.\n     *\n     * The value returned MUST be normalized to lowercase, per RFC 3986\n     * Section 3.1.\n     *\n     * The trailing \":\" character is not part of the scheme and MUST NOT be\n     * added.\n     *\n     * @see https://tools.ietf.org/html/rfc3986#section-3.1\n     * @return string The URI scheme.\n     */\n    public function getScheme();\n\n    /**\n     * Retrieve the authority component of the URI.\n     *\n     * If no authority information is present, this method MUST return an empty\n     * string.\n     *\n     * The authority syntax of the URI is:\n     *\n     * <pre>\n     * [user-info@]host[:port]\n     * </pre>\n     *\n     * If the port component is not set or is the standard port for the current\n     * scheme, it SHOULD NOT be included.\n     *\n     * @see https://tools.ietf.org/html/rfc3986#section-3.2\n     * @return string The URI authority, in \"[user-info@]host[:port]\" format.\n     */\n    public function getAuthority();\n\n    /**\n     * Retrieve the user information component of the URI.\n     *\n     * If no user information is present, this method MUST return an empty\n     * string.\n     *\n     * If a user is present in the URI, this will return that value;\n     * additionally, if the password is also present, it will be appended to the\n     * user value, with a colon (\":\") separating the values.\n     *\n     * The trailing \"@\" character is not part of the user information and MUST\n     * NOT be added.\n     *\n     * @return string The URI user information, in \"username[:password]\" format.\n     */\n    public function getUserInfo();\n\n    /**\n     * Retrieve the host component of the URI.\n     *\n     * If no host is present, this method MUST return an empty string.\n     *\n     * The value returned MUST be normalized to lowercase, per RFC 3986\n     * Section 3.2.2.\n     *\n     * @see http://tools.ietf.org/html/rfc3986#section-3.2.2\n     * @return string The URI host.\n     */\n    public function getHost();\n\n    /**\n     * Retrieve the port component of the URI.\n     *\n     * If a port is present, and it is non-standard for the current scheme,\n     * this method MUST return it as an integer. If the port is the standard port\n     * used with the current scheme, this method SHOULD return null.\n     *\n     * If no port is present, and no scheme is present, this method MUST return\n     * a null value.\n     *\n     * If no port is present, but a scheme is present, this method MAY return\n     * the standard port for that scheme, but SHOULD return null.\n     *\n     * @return null|int The URI port.\n     */\n    public function getPort();\n\n    /**\n     * Retrieve the path component of the URI.\n     *\n     * The path can either be empty or absolute (starting with a slash) or\n     * rootless (not starting with a slash). Implementations MUST support all\n     * three syntaxes.\n     *\n     * Normally, the empty path \"\" and absolute path \"/\" are considered equal as\n     * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically\n     * do this normalization because in contexts with a trimmed base path, e.g.\n     * the front controller, this difference becomes significant. It's the task\n     * of the user to handle both \"\" and \"/\".\n     *\n     * The value returned MUST be percent-encoded, but MUST NOT double-encode\n     * any characters. To determine what characters to encode, please refer to\n     * RFC 3986, Sections 2 and 3.3.\n     *\n     * As an example, if the value should include a slash (\"/\") not intended as\n     * delimiter between path segments, that value MUST be passed in encoded\n     * form (e.g., \"%2F\") to the instance.\n     *\n     * @see https://tools.ietf.org/html/rfc3986#section-2\n     * @see https://tools.ietf.org/html/rfc3986#section-3.3\n     * @return string The URI path.\n     */\n    public function getPath();\n\n    /**\n     * Retrieve the query string of the URI.\n     *\n     * If no query string is present, this method MUST return an empty string.\n     *\n     * The leading \"?\" character is not part of the query and MUST NOT be\n     * added.\n     *\n     * The value returned MUST be percent-encoded, but MUST NOT double-encode\n     * any characters. To determine what characters to encode, please refer to\n     * RFC 3986, Sections 2 and 3.4.\n     *\n     * As an example, if a value in a key/value pair of the query string should\n     * include an ampersand (\"&\") not intended as a delimiter between values,\n     * that value MUST be passed in encoded form (e.g., \"%26\") to the instance.\n     *\n     * @see https://tools.ietf.org/html/rfc3986#section-2\n     * @see https://tools.ietf.org/html/rfc3986#section-3.4\n     * @return string The URI query string.\n     */\n    public function getQuery();\n\n    /**\n     * Retrieve the fragment component of the URI.\n     *\n     * If no fragment is present, this method MUST return an empty string.\n     *\n     * The leading \"#\" character is not part of the fragment and MUST NOT be\n     * added.\n     *\n     * The value returned MUST be percent-encoded, but MUST NOT double-encode\n     * any characters. To determine what characters to encode, please refer to\n     * RFC 3986, Sections 2 and 3.5.\n     *\n     * @see https://tools.ietf.org/html/rfc3986#section-2\n     * @see https://tools.ietf.org/html/rfc3986#section-3.5\n     * @return string The URI fragment.\n     */\n    public function getFragment();\n\n    /**\n     * Return an instance with the specified scheme.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified scheme.\n     *\n     * Implementations MUST support the schemes \"http\" and \"https\" case\n     * insensitively, and MAY accommodate other schemes if required.\n     *\n     * An empty scheme is equivalent to removing the scheme.\n     *\n     * @param string $scheme The scheme to use with the new instance.\n     * @return static A new instance with the specified scheme.\n     * @throws \\InvalidArgumentException for invalid or unsupported schemes.\n     */\n    public function withScheme($scheme);\n\n    /**\n     * Return an instance with the specified user information.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified user information.\n     *\n     * Password is optional, but the user information MUST include the\n     * user; an empty string for the user is equivalent to removing user\n     * information.\n     *\n     * @param string $user The user name to use for authority.\n     * @param null|string $password The password associated with $user.\n     * @return static A new instance with the specified user information.\n     */\n    public function withUserInfo($user, $password = null);\n\n    /**\n     * Return an instance with the specified host.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified host.\n     *\n     * An empty host value is equivalent to removing the host.\n     *\n     * @param string $host The hostname to use with the new instance.\n     * @return static A new instance with the specified host.\n     * @throws \\InvalidArgumentException for invalid hostnames.\n     */\n    public function withHost($host);\n\n    /**\n     * Return an instance with the specified port.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified port.\n     *\n     * Implementations MUST raise an exception for ports outside the\n     * established TCP and UDP port ranges.\n     *\n     * A null value provided for the port is equivalent to removing the port\n     * information.\n     *\n     * @param null|int $port The port to use with the new instance; a null value\n     *     removes the port information.\n     * @return static A new instance with the specified port.\n     * @throws \\InvalidArgumentException for invalid ports.\n     */\n    public function withPort($port);\n\n    /**\n     * Return an instance with the specified path.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified path.\n     *\n     * The path can either be empty or absolute (starting with a slash) or\n     * rootless (not starting with a slash). Implementations MUST support all\n     * three syntaxes.\n     *\n     * If the path is intended to be domain-relative rather than path relative then\n     * it must begin with a slash (\"/\"). Paths not starting with a slash (\"/\")\n     * are assumed to be relative to some base path known to the application or\n     * consumer.\n     *\n     * Users can provide both encoded and decoded path characters.\n     * Implementations ensure the correct encoding as outlined in getPath().\n     *\n     * @param string $path The path to use with the new instance.\n     * @return static A new instance with the specified path.\n     * @throws \\InvalidArgumentException for invalid paths.\n     */\n    public function withPath($path);\n\n    /**\n     * Return an instance with the specified query string.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified query string.\n     *\n     * Users can provide both encoded and decoded query characters.\n     * Implementations ensure the correct encoding as outlined in getQuery().\n     *\n     * An empty query string value is equivalent to removing the query string.\n     *\n     * @param string $query The query string to use with the new instance.\n     * @return static A new instance with the specified query string.\n     * @throws \\InvalidArgumentException for invalid query strings.\n     */\n    public function withQuery($query);\n\n    /**\n     * Return an instance with the specified URI fragment.\n     *\n     * This method MUST retain the state of the current instance, and return\n     * an instance that contains the specified URI fragment.\n     *\n     * Users can provide both encoded and decoded fragment characters.\n     * Implementations ensure the correct encoding as outlined in getFragment().\n     *\n     * An empty fragment value is equivalent to removing the fragment.\n     *\n     * @param string $fragment The fragment to use with the new instance.\n     * @return static A new instance with the specified fragment.\n     */\n    public function withFragment($fragment);\n\n    /**\n     * Return the string representation as a URI reference.\n     *\n     * Depending on which components of the URI are present, the resulting\n     * string is either a full URI or relative reference according to RFC 3986,\n     * Section 4.1. The method concatenates the various components of the URI,\n     * using the appropriate delimiters:\n     *\n     * - If a scheme is present, it MUST be suffixed by \":\".\n     * - If an authority is present, it MUST be prefixed by \"//\".\n     * - The path can be concatenated without delimiters. But there are two\n     *   cases where the path has to be adjusted to make the URI reference\n     *   valid as PHP does not allow to throw an exception in __toString():\n     *     - If the path is rootless and an authority is present, the path MUST\n     *       be prefixed by \"/\".\n     *     - If the path is starting with more than one \"/\" and no authority is\n     *       present, the starting slashes MUST be reduced to one.\n     * - If a query is present, it MUST be prefixed by \"?\".\n     * - If a fragment is present, it MUST be prefixed by \"#\".\n     *\n     * @see http://tools.ietf.org/html/rfc3986#section-4.1\n     * @return string\n     */\n    public function __toString();\n}\n"
  },
  {
    "path": "vendor/psr/log/LICENSE",
    "content": "Copyright (c) 2012 PHP Framework Interoperability Group\n\nPermission is hereby granted, free of charge, to any person obtaining a copy \nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights \nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is \nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in \nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/AbstractLogger.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * This is a simple Logger implementation that other Loggers can inherit from.\n *\n * It simply delegates all log-level-specific methods to the `log` method to\n * reduce boilerplate code that a simple Logger that does the same thing with\n * messages regardless of the error level has to implement.\n */\nabstract class AbstractLogger implements LoggerInterface\n{\n    /**\n     * System is unusable.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function emergency($message, array $context = array())\n    {\n        $this->log(LogLevel::EMERGENCY, $message, $context);\n    }\n\n    /**\n     * Action must be taken immediately.\n     *\n     * Example: Entire website down, database unavailable, etc. This should\n     * trigger the SMS alerts and wake you up.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function alert($message, array $context = array())\n    {\n        $this->log(LogLevel::ALERT, $message, $context);\n    }\n\n    /**\n     * Critical conditions.\n     *\n     * Example: Application component unavailable, unexpected exception.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function critical($message, array $context = array())\n    {\n        $this->log(LogLevel::CRITICAL, $message, $context);\n    }\n\n    /**\n     * Runtime errors that do not require immediate action but should typically\n     * be logged and monitored.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function error($message, array $context = array())\n    {\n        $this->log(LogLevel::ERROR, $message, $context);\n    }\n\n    /**\n     * Exceptional occurrences that are not errors.\n     *\n     * Example: Use of deprecated APIs, poor use of an API, undesirable things\n     * that are not necessarily wrong.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function warning($message, array $context = array())\n    {\n        $this->log(LogLevel::WARNING, $message, $context);\n    }\n\n    /**\n     * Normal but significant events.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function notice($message, array $context = array())\n    {\n        $this->log(LogLevel::NOTICE, $message, $context);\n    }\n\n    /**\n     * Interesting events.\n     *\n     * Example: User logs in, SQL logs.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function info($message, array $context = array())\n    {\n        $this->log(LogLevel::INFO, $message, $context);\n    }\n\n    /**\n     * Detailed debug information.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function debug($message, array $context = array())\n    {\n        $this->log(LogLevel::DEBUG, $message, $context);\n    }\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/InvalidArgumentException.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\nclass InvalidArgumentException extends \\InvalidArgumentException\n{\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/LogLevel.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * Describes log levels.\n */\nclass LogLevel\n{\n    const EMERGENCY = 'emergency';\n    const ALERT     = 'alert';\n    const CRITICAL  = 'critical';\n    const ERROR     = 'error';\n    const WARNING   = 'warning';\n    const NOTICE    = 'notice';\n    const INFO      = 'info';\n    const DEBUG     = 'debug';\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/LoggerAwareInterface.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * Describes a logger-aware instance.\n */\ninterface LoggerAwareInterface\n{\n    /**\n     * Sets a logger instance on the object.\n     *\n     * @param LoggerInterface $logger\n     *\n     * @return void\n     */\n    public function setLogger(LoggerInterface $logger);\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/LoggerAwareTrait.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * Basic Implementation of LoggerAwareInterface.\n */\ntrait LoggerAwareTrait\n{\n    /**\n     * The logger instance.\n     *\n     * @var LoggerInterface|null\n     */\n    protected $logger;\n\n    /**\n     * Sets a logger.\n     *\n     * @param LoggerInterface $logger\n     */\n    public function setLogger(LoggerInterface $logger)\n    {\n        $this->logger = $logger;\n    }\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/LoggerInterface.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * Describes a logger instance.\n *\n * The message MUST be a string or object implementing __toString().\n *\n * The message MAY contain placeholders in the form: {foo} where foo\n * will be replaced by the context data in key \"foo\".\n *\n * The context array can contain arbitrary data. The only assumption that\n * can be made by implementors is that if an Exception instance is given\n * to produce a stack trace, it MUST be in a key named \"exception\".\n *\n * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md\n * for the full interface specification.\n */\ninterface LoggerInterface\n{\n    /**\n     * System is unusable.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function emergency($message, array $context = array());\n\n    /**\n     * Action must be taken immediately.\n     *\n     * Example: Entire website down, database unavailable, etc. This should\n     * trigger the SMS alerts and wake you up.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function alert($message, array $context = array());\n\n    /**\n     * Critical conditions.\n     *\n     * Example: Application component unavailable, unexpected exception.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function critical($message, array $context = array());\n\n    /**\n     * Runtime errors that do not require immediate action but should typically\n     * be logged and monitored.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function error($message, array $context = array());\n\n    /**\n     * Exceptional occurrences that are not errors.\n     *\n     * Example: Use of deprecated APIs, poor use of an API, undesirable things\n     * that are not necessarily wrong.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function warning($message, array $context = array());\n\n    /**\n     * Normal but significant events.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function notice($message, array $context = array());\n\n    /**\n     * Interesting events.\n     *\n     * Example: User logs in, SQL logs.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function info($message, array $context = array());\n\n    /**\n     * Detailed debug information.\n     *\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     */\n    public function debug($message, array $context = array());\n\n    /**\n     * Logs with an arbitrary level.\n     *\n     * @param mixed   $level\n     * @param string  $message\n     * @param mixed[] $context\n     *\n     * @return void\n     *\n     * @throws \\Psr\\Log\\InvalidArgumentException\n     */\n    public function log($level, $message, array $context = array());\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/LoggerTrait.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * This is a simple Logger trait that classes unable to extend AbstractLogger\n * (because they extend another class, etc) can include.\n *\n * It simply delegates all log-level-specific methods to the `log` method to\n * reduce boilerplate code that a simple Logger that does the same thing with\n * messages regardless of the error level has to implement.\n */\ntrait LoggerTrait\n{\n    /**\n     * System is unusable.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function emergency($message, array $context = array())\n    {\n        $this->log(LogLevel::EMERGENCY, $message, $context);\n    }\n\n    /**\n     * Action must be taken immediately.\n     *\n     * Example: Entire website down, database unavailable, etc. This should\n     * trigger the SMS alerts and wake you up.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function alert($message, array $context = array())\n    {\n        $this->log(LogLevel::ALERT, $message, $context);\n    }\n\n    /**\n     * Critical conditions.\n     *\n     * Example: Application component unavailable, unexpected exception.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function critical($message, array $context = array())\n    {\n        $this->log(LogLevel::CRITICAL, $message, $context);\n    }\n\n    /**\n     * Runtime errors that do not require immediate action but should typically\n     * be logged and monitored.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function error($message, array $context = array())\n    {\n        $this->log(LogLevel::ERROR, $message, $context);\n    }\n\n    /**\n     * Exceptional occurrences that are not errors.\n     *\n     * Example: Use of deprecated APIs, poor use of an API, undesirable things\n     * that are not necessarily wrong.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function warning($message, array $context = array())\n    {\n        $this->log(LogLevel::WARNING, $message, $context);\n    }\n\n    /**\n     * Normal but significant events.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function notice($message, array $context = array())\n    {\n        $this->log(LogLevel::NOTICE, $message, $context);\n    }\n\n    /**\n     * Interesting events.\n     *\n     * Example: User logs in, SQL logs.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function info($message, array $context = array())\n    {\n        $this->log(LogLevel::INFO, $message, $context);\n    }\n\n    /**\n     * Detailed debug information.\n     *\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     */\n    public function debug($message, array $context = array())\n    {\n        $this->log(LogLevel::DEBUG, $message, $context);\n    }\n\n    /**\n     * Logs with an arbitrary level.\n     *\n     * @param mixed  $level\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     *\n     * @throws \\Psr\\Log\\InvalidArgumentException\n     */\n    abstract public function log($level, $message, array $context = array());\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/NullLogger.php",
    "content": "<?php\n\nnamespace Psr\\Log;\n\n/**\n * This Logger can be used to avoid conditional log calls.\n *\n * Logging should always be optional, and if no logger is provided to your\n * library creating a NullLogger instance to have something to throw logs at\n * is a good way to avoid littering your code with `if ($this->logger) { }`\n * blocks.\n */\nclass NullLogger extends AbstractLogger\n{\n    /**\n     * Logs with an arbitrary level.\n     *\n     * @param mixed  $level\n     * @param string $message\n     * @param array  $context\n     *\n     * @return void\n     *\n     * @throws \\Psr\\Log\\InvalidArgumentException\n     */\n    public function log($level, $message, array $context = array())\n    {\n        // noop\n    }\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/Test/DummyTest.php",
    "content": "<?php\n\nnamespace Psr\\Log\\Test;\n\n/**\n * This class is internal and does not follow the BC promise.\n *\n * Do NOT use this class in any way.\n *\n * @internal\n */\nclass DummyTest\n{\n    public function __toString()\n    {\n        return 'DummyTest';\n    }\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php",
    "content": "<?php\n\nnamespace Psr\\Log\\Test;\n\nuse Psr\\Log\\LoggerInterface;\nuse Psr\\Log\\LogLevel;\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * Provides a base test class for ensuring compliance with the LoggerInterface.\n *\n * Implementors can extend the class and implement abstract methods to run this\n * as part of their test suite.\n */\nabstract class LoggerInterfaceTest extends TestCase\n{\n    /**\n     * @return LoggerInterface\n     */\n    abstract public function getLogger();\n\n    /**\n     * This must return the log messages in order.\n     *\n     * The simple formatting of the messages is: \"<LOG LEVEL> <MESSAGE>\".\n     *\n     * Example ->error('Foo') would yield \"error Foo\".\n     *\n     * @return string[]\n     */\n    abstract public function getLogs();\n\n    public function testImplements()\n    {\n        $this->assertInstanceOf('Psr\\Log\\LoggerInterface', $this->getLogger());\n    }\n\n    /**\n     * @dataProvider provideLevelsAndMessages\n     */\n    public function testLogsAtAllLevels($level, $message)\n    {\n        $logger = $this->getLogger();\n        $logger->{$level}($message, array('user' => 'Bob'));\n        $logger->log($level, $message, array('user' => 'Bob'));\n\n        $expected = array(\n            $level.' message of level '.$level.' with context: Bob',\n            $level.' message of level '.$level.' with context: Bob',\n        );\n        $this->assertEquals($expected, $this->getLogs());\n    }\n\n    public function provideLevelsAndMessages()\n    {\n        return array(\n            LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),\n            LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),\n            LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),\n            LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),\n            LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),\n            LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),\n            LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),\n            LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),\n        );\n    }\n\n    /**\n     * @expectedException \\Psr\\Log\\InvalidArgumentException\n     */\n    public function testThrowsOnInvalidLevel()\n    {\n        $logger = $this->getLogger();\n        $logger->log('invalid level', 'Foo');\n    }\n\n    public function testContextReplacement()\n    {\n        $logger = $this->getLogger();\n        $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));\n\n        $expected = array('info {Message {nothing} Bob Bar a}');\n        $this->assertEquals($expected, $this->getLogs());\n    }\n\n    public function testObjectCastToString()\n    {\n        if (method_exists($this, 'createPartialMock')) {\n            $dummy = $this->createPartialMock('Psr\\Log\\Test\\DummyTest', array('__toString'));\n        } else {\n            $dummy = $this->getMock('Psr\\Log\\Test\\DummyTest', array('__toString'));\n        }\n        $dummy->expects($this->once())\n            ->method('__toString')\n            ->will($this->returnValue('DUMMY'));\n\n        $this->getLogger()->warning($dummy);\n\n        $expected = array('warning DUMMY');\n        $this->assertEquals($expected, $this->getLogs());\n    }\n\n    public function testContextCanContainAnything()\n    {\n        $closed = fopen('php://memory', 'r');\n        fclose($closed);\n\n        $context = array(\n            'bool' => true,\n            'null' => null,\n            'string' => 'Foo',\n            'int' => 0,\n            'float' => 0.5,\n            'nested' => array('with object' => new DummyTest),\n            'object' => new \\DateTime,\n            'resource' => fopen('php://memory', 'r'),\n            'closed' => $closed,\n        );\n\n        $this->getLogger()->warning('Crazy context data', $context);\n\n        $expected = array('warning Crazy context data');\n        $this->assertEquals($expected, $this->getLogs());\n    }\n\n    public function testContextExceptionKeyCanBeExceptionOrOtherValues()\n    {\n        $logger = $this->getLogger();\n        $logger->warning('Random message', array('exception' => 'oops'));\n        $logger->critical('Uncaught Exception!', array('exception' => new \\LogicException('Fail')));\n\n        $expected = array(\n            'warning Random message',\n            'critical Uncaught Exception!'\n        );\n        $this->assertEquals($expected, $this->getLogs());\n    }\n}\n"
  },
  {
    "path": "vendor/psr/log/Psr/Log/Test/TestLogger.php",
    "content": "<?php\n\nnamespace Psr\\Log\\Test;\n\nuse Psr\\Log\\AbstractLogger;\n\n/**\n * Used for testing purposes.\n *\n * It records all records and gives you access to them for verification.\n *\n * @method bool hasEmergency($record)\n * @method bool hasAlert($record)\n * @method bool hasCritical($record)\n * @method bool hasError($record)\n * @method bool hasWarning($record)\n * @method bool hasNotice($record)\n * @method bool hasInfo($record)\n * @method bool hasDebug($record)\n *\n * @method bool hasEmergencyRecords()\n * @method bool hasAlertRecords()\n * @method bool hasCriticalRecords()\n * @method bool hasErrorRecords()\n * @method bool hasWarningRecords()\n * @method bool hasNoticeRecords()\n * @method bool hasInfoRecords()\n * @method bool hasDebugRecords()\n *\n * @method bool hasEmergencyThatContains($message)\n * @method bool hasAlertThatContains($message)\n * @method bool hasCriticalThatContains($message)\n * @method bool hasErrorThatContains($message)\n * @method bool hasWarningThatContains($message)\n * @method bool hasNoticeThatContains($message)\n * @method bool hasInfoThatContains($message)\n * @method bool hasDebugThatContains($message)\n *\n * @method bool hasEmergencyThatMatches($message)\n * @method bool hasAlertThatMatches($message)\n * @method bool hasCriticalThatMatches($message)\n * @method bool hasErrorThatMatches($message)\n * @method bool hasWarningThatMatches($message)\n * @method bool hasNoticeThatMatches($message)\n * @method bool hasInfoThatMatches($message)\n * @method bool hasDebugThatMatches($message)\n *\n * @method bool hasEmergencyThatPasses($message)\n * @method bool hasAlertThatPasses($message)\n * @method bool hasCriticalThatPasses($message)\n * @method bool hasErrorThatPasses($message)\n * @method bool hasWarningThatPasses($message)\n * @method bool hasNoticeThatPasses($message)\n * @method bool hasInfoThatPasses($message)\n * @method bool hasDebugThatPasses($message)\n */\nclass TestLogger extends AbstractLogger\n{\n    /**\n     * @var array\n     */\n    public $records = [];\n\n    public $recordsByLevel = [];\n\n    /**\n     * @inheritdoc\n     */\n    public function log($level, $message, array $context = [])\n    {\n        $record = [\n            'level' => $level,\n            'message' => $message,\n            'context' => $context,\n        ];\n\n        $this->recordsByLevel[$record['level']][] = $record;\n        $this->records[] = $record;\n    }\n\n    public function hasRecords($level)\n    {\n        return isset($this->recordsByLevel[$level]);\n    }\n\n    public function hasRecord($record, $level)\n    {\n        if (is_string($record)) {\n            $record = ['message' => $record];\n        }\n        return $this->hasRecordThatPasses(function ($rec) use ($record) {\n            if ($rec['message'] !== $record['message']) {\n                return false;\n            }\n            if (isset($record['context']) && $rec['context'] !== $record['context']) {\n                return false;\n            }\n            return true;\n        }, $level);\n    }\n\n    public function hasRecordThatContains($message, $level)\n    {\n        return $this->hasRecordThatPasses(function ($rec) use ($message) {\n            return strpos($rec['message'], $message) !== false;\n        }, $level);\n    }\n\n    public function hasRecordThatMatches($regex, $level)\n    {\n        return $this->hasRecordThatPasses(function ($rec) use ($regex) {\n            return preg_match($regex, $rec['message']) > 0;\n        }, $level);\n    }\n\n    public function hasRecordThatPasses(callable $predicate, $level)\n    {\n        if (!isset($this->recordsByLevel[$level])) {\n            return false;\n        }\n        foreach ($this->recordsByLevel[$level] as $i => $rec) {\n            if (call_user_func($predicate, $rec, $i)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public function __call($method, $args)\n    {\n        if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {\n            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];\n            $level = strtolower($matches[2]);\n            if (method_exists($this, $genericMethod)) {\n                $args[] = $level;\n                return call_user_func_array([$this, $genericMethod], $args);\n            }\n        }\n        throw new \\BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');\n    }\n\n    public function reset()\n    {\n        $this->records = [];\n        $this->recordsByLevel = [];\n    }\n}\n"
  },
  {
    "path": "vendor/psr/log/README.md",
    "content": "PSR Log\n=======\n\nThis repository holds all interfaces/classes/traits related to\n[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).\n\nNote that this is not a logger of its own. It is merely an interface that\ndescribes a logger. See the specification for more details.\n\nInstallation\n------------\n\n```bash\ncomposer require psr/log\n```\n\nUsage\n-----\n\nIf you need a logger, you can use the interface like this:\n\n```php\n<?php\n\nuse Psr\\Log\\LoggerInterface;\n\nclass Foo\n{\n    private $logger;\n\n    public function __construct(LoggerInterface $logger = null)\n    {\n        $this->logger = $logger;\n    }\n\n    public function doSomething()\n    {\n        if ($this->logger) {\n            $this->logger->info('Doing work');\n        }\n           \n        try {\n            $this->doSomethingElse();\n        } catch (Exception $exception) {\n            $this->logger->error('Oh no!', array('exception' => $exception));\n        }\n\n        // do something useful\n    }\n}\n```\n\nYou can then pick one of the implementations of the interface to get a logger.\n\nIf you want to implement the interface, you can require this package and\nimplement `Psr\\Log\\LoggerInterface` in your code. Please read the\n[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)\nfor details.\n"
  },
  {
    "path": "vendor/psr/log/composer.json",
    "content": "{\n    \"name\": \"psr/log\",\n    \"description\": \"Common interface for logging libraries\",\n    \"keywords\": [\"psr\", \"psr-3\", \"log\"],\n    \"homepage\": \"https://github.com/php-fig/log\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"PHP-FIG\",\n            \"homepage\": \"https://www.php-fig.org/\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=5.3.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Psr\\\\Log\\\\\": \"Psr/Log/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.1.x-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/psr/simple-cache/.editorconfig",
    "content": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_size = 4\nindent_style = space\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": "vendor/psr/simple-cache/LICENSE.md",
    "content": "# The MIT License (MIT)\n\nCopyright (c) 2016 PHP Framework Interoperability Group\n\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n"
  },
  {
    "path": "vendor/psr/simple-cache/README.md",
    "content": "PHP FIG Simple Cache PSR\n========================\n\nThis repository holds all interfaces related to PSR-16.\n\nNote that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See [the specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md) for more details.\n\nYou can find implementations of the specification by looking for packages providing the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) virtual package.\n"
  },
  {
    "path": "vendor/psr/simple-cache/composer.json",
    "content": "{\n    \"name\": \"psr/simple-cache\",\n    \"description\": \"Common interfaces for simple caching\",\n    \"keywords\": [\"psr\", \"psr-16\", \"cache\", \"simple-cache\", \"caching\"],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"PHP-FIG\",\n            \"homepage\": \"http://www.php-fig.org/\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=5.3.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Psr\\\\SimpleCache\\\\\": \"src/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"1.0.x-dev\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/psr/simple-cache/src/CacheException.php",
    "content": "<?php\n\nnamespace Psr\\SimpleCache;\n\n/**\n * Interface used for all types of exceptions thrown by the implementing library.\n */\ninterface CacheException\n{\n}\n"
  },
  {
    "path": "vendor/psr/simple-cache/src/CacheInterface.php",
    "content": "<?php\n\nnamespace Psr\\SimpleCache;\n\ninterface CacheInterface\n{\n    /**\n     * Fetches a value from the cache.\n     *\n     * @param string $key     The unique key of this item in the cache.\n     * @param mixed  $default Default value to return if the key does not exist.\n     *\n     * @return mixed The value of the item from the cache, or $default in case of cache miss.\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if the $key string is not a legal value.\n     */\n    public function get($key, $default = null);\n\n    /**\n     * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.\n     *\n     * @param string                 $key   The key of the item to store.\n     * @param mixed                  $value The value of the item to store, must be serializable.\n     * @param null|int|\\DateInterval $ttl   Optional. The TTL value of this item. If no value is sent and\n     *                                      the driver supports TTL then the library may set a default value\n     *                                      for it or let the driver take care of that.\n     *\n     * @return bool True on success and false on failure.\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if the $key string is not a legal value.\n     */\n    public function set($key, $value, $ttl = null);\n\n    /**\n     * Delete an item from the cache by its unique key.\n     *\n     * @param string $key The unique cache key of the item to delete.\n     *\n     * @return bool True if the item was successfully removed. False if there was an error.\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if the $key string is not a legal value.\n     */\n    public function delete($key);\n\n    /**\n     * Wipes clean the entire cache's keys.\n     *\n     * @return bool True on success and false on failure.\n     */\n    public function clear();\n\n    /**\n     * Obtains multiple cache items by their unique keys.\n     *\n     * @param iterable $keys    A list of keys that can obtained in a single operation.\n     * @param mixed    $default Default value to return for keys that do not exist.\n     *\n     * @return iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value.\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if $keys is neither an array nor a Traversable,\n     *   or if any of the $keys are not a legal value.\n     */\n    public function getMultiple($keys, $default = null);\n\n    /**\n     * Persists a set of key => value pairs in the cache, with an optional TTL.\n     *\n     * @param iterable               $values A list of key => value pairs for a multiple-set operation.\n     * @param null|int|\\DateInterval $ttl    Optional. The TTL value of this item. If no value is sent and\n     *                                       the driver supports TTL then the library may set a default value\n     *                                       for it or let the driver take care of that.\n     *\n     * @return bool True on success and false on failure.\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if $values is neither an array nor a Traversable,\n     *   or if any of the $values are not a legal value.\n     */\n    public function setMultiple($values, $ttl = null);\n\n    /**\n     * Deletes multiple cache items in a single operation.\n     *\n     * @param iterable $keys A list of string-based keys to be deleted.\n     *\n     * @return bool True if the items were successfully removed. False if there was an error.\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if $keys is neither an array nor a Traversable,\n     *   or if any of the $keys are not a legal value.\n     */\n    public function deleteMultiple($keys);\n\n    /**\n     * Determines whether an item is present in the cache.\n     *\n     * NOTE: It is recommended that has() is only to be used for cache warming type purposes\n     * and not to be used within your live applications operations for get/set, as this method\n     * is subject to a race condition where your has() will return true and immediately after,\n     * another script can remove it making the state of your app out of date.\n     *\n     * @param string $key The cache item key.\n     *\n     * @return bool\n     *\n     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n     *   MUST be thrown if the $key string is not a legal value.\n     */\n    public function has($key);\n}\n"
  },
  {
    "path": "vendor/psr/simple-cache/src/InvalidArgumentException.php",
    "content": "<?php\n\nnamespace Psr\\SimpleCache;\n\n/**\n * Exception interface for invalid cache arguments.\n *\n * When an invalid argument is passed it must throw an exception which implements\n * this interface\n */\ninterface InvalidArgumentException extends CacheException\n{\n}\n"
  },
  {
    "path": "vendor/ralouphie/getallheaders/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Ralph Khattar\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "vendor/ralouphie/getallheaders/README.md",
    "content": "getallheaders\n=============\n\nPHP `getallheaders()` polyfill. Compatible with PHP >= 5.3.\n\n[![Build Status](https://travis-ci.org/ralouphie/getallheaders.svg?branch=master)](https://travis-ci.org/ralouphie/getallheaders)\n[![Coverage Status](https://coveralls.io/repos/ralouphie/getallheaders/badge.png?branch=master)](https://coveralls.io/r/ralouphie/getallheaders?branch=master)\n[![Latest Stable Version](https://poser.pugx.org/ralouphie/getallheaders/v/stable.png)](https://packagist.org/packages/ralouphie/getallheaders)\n[![Latest Unstable Version](https://poser.pugx.org/ralouphie/getallheaders/v/unstable.png)](https://packagist.org/packages/ralouphie/getallheaders)\n[![License](https://poser.pugx.org/ralouphie/getallheaders/license.png)](https://packagist.org/packages/ralouphie/getallheaders)\n\n\nThis is a simple polyfill for [`getallheaders()`](http://www.php.net/manual/en/function.getallheaders.php).\n\n## Install\n\nFor PHP version **`>= 5.6`**:\n\n```\ncomposer require ralouphie/getallheaders\n```\n\nFor PHP version **`< 5.6`**:\n\n```\ncomposer require ralouphie/getallheaders \"^2\"\n```\n"
  },
  {
    "path": "vendor/ralouphie/getallheaders/composer.json",
    "content": "{\n\t\"name\": \"ralouphie/getallheaders\",\n\t\"description\": \"A polyfill for getallheaders.\",\n\t\"license\": \"MIT\",\n\t\"authors\": [\n\t\t{\n\t\t\t\"name\": \"Ralph Khattar\",\n\t\t\t\"email\": \"ralph.khattar@gmail.com\"\n\t\t}\n\t],\n\t\"require\": {\n\t\t\"php\": \">=5.6\"\n\t},\n\t\"require-dev\": {\n\t\t\"phpunit/phpunit\": \"^5 || ^6.5\",\n\t\t\"php-coveralls/php-coveralls\": \"^2.1\"\n\t},\n\t\"autoload\": {\n\t\t\"files\": [\"src/getallheaders.php\"]\n\t},\n\t\"autoload-dev\": {\n\t\t\"psr-4\": {\n\t\t\t\"getallheaders\\\\Tests\\\\\": \"tests/\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "vendor/ralouphie/getallheaders/src/getallheaders.php",
    "content": "<?php\n\nif (!function_exists('getallheaders')) {\n\n    /**\n     * Get all HTTP header key/values as an associative array for the current request.\n     *\n     * @return string[string] The HTTP header key/value pairs.\n     */\n    function getallheaders()\n    {\n        $headers = array();\n\n        $copy_server = array(\n            'CONTENT_TYPE'   => 'Content-Type',\n            'CONTENT_LENGTH' => 'Content-Length',\n            'CONTENT_MD5'    => 'Content-Md5',\n        );\n\n        foreach ($_SERVER as $key => $value) {\n            if (substr($key, 0, 5) === 'HTTP_') {\n                $key = substr($key, 5);\n                if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) {\n                    $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));\n                    $headers[$key] = $value;\n                }\n            } elseif (isset($copy_server[$key])) {\n                $headers[$copy_server[$key]] = $value;\n            }\n        }\n\n        if (!isset($headers['Authorization'])) {\n            if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {\n                $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];\n            } elseif (isset($_SERVER['PHP_AUTH_USER'])) {\n                $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';\n                $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass);\n            } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {\n                $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];\n            }\n        }\n\n        return $headers;\n    }\n\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/LICENSE",
    "content": "Copyright (c) 2015-2019 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/Mbstring.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Polyfill\\Mbstring;\n\n/**\n * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.\n *\n * Implemented:\n * - mb_chr                  - Returns a specific character from its Unicode code point\n * - mb_convert_encoding     - Convert character encoding\n * - mb_convert_variables    - Convert character code in variable(s)\n * - mb_decode_mimeheader    - Decode string in MIME header field\n * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED\n * - mb_decode_numericentity - Decode HTML numeric string reference to character\n * - mb_encode_numericentity - Encode character to HTML numeric string reference\n * - mb_convert_case         - Perform case folding on a string\n * - mb_detect_encoding      - Detect character encoding\n * - mb_get_info             - Get internal settings of mbstring\n * - mb_http_input           - Detect HTTP input character encoding\n * - mb_http_output          - Set/Get HTTP output character encoding\n * - mb_internal_encoding    - Set/Get internal character encoding\n * - mb_list_encodings       - Returns an array of all supported encodings\n * - mb_ord                  - Returns the Unicode code point of a character\n * - mb_output_handler       - Callback function converts character encoding in output buffer\n * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters\n * - mb_strlen               - Get string length\n * - mb_strpos               - Find position of first occurrence of string in a string\n * - mb_strrpos              - Find position of last occurrence of a string in a string\n * - mb_str_split            - Convert a string to an array\n * - mb_strtolower           - Make a string lowercase\n * - mb_strtoupper           - Make a string uppercase\n * - mb_substitute_character - Set/Get substitution character\n * - mb_substr               - Get part of string\n * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive\n * - mb_stristr              - Finds first occurrence of a string within another, case insensitive\n * - mb_strrchr              - Finds the last occurrence of a character in a string within another\n * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive\n * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive\n * - mb_strstr               - Finds first occurrence of a string within another\n * - mb_strwidth             - Return width of string\n * - mb_substr_count         - Count the number of substring occurrences\n *\n * Not implemented:\n * - mb_convert_kana         - Convert \"kana\" one from another (\"zen-kaku\", \"han-kaku\" and more)\n * - mb_ereg_*               - Regular expression with multibyte support\n * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable\n * - mb_preferred_mime_name  - Get MIME charset string\n * - mb_regex_encoding       - Returns current encoding for multibyte regex as string\n * - mb_regex_set_options    - Set/Get the default options for mbregex functions\n * - mb_send_mail            - Send encoded mail\n * - mb_split                - Split multibyte string using regular expression\n * - mb_strcut               - Get part of string\n * - mb_strimwidth           - Get truncated string with specified width\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class Mbstring\n{\n    public const MB_CASE_FOLD = \\PHP_INT_MAX;\n\n    private const CASE_FOLD = [\n        ['µ', 'ſ', \"\\xCD\\x85\", 'ς', \"\\xCF\\x90\", \"\\xCF\\x91\", \"\\xCF\\x95\", \"\\xCF\\x96\", \"\\xCF\\xB0\", \"\\xCF\\xB1\", \"\\xCF\\xB5\", \"\\xE1\\xBA\\x9B\", \"\\xE1\\xBE\\xBE\"],\n        ['μ', 's', 'ι',        'σ', 'β',        'θ',        'φ',        'π',        'κ',        'ρ',        'ε',        \"\\xE1\\xB9\\xA1\", 'ι'],\n    ];\n\n    private static $encodingList = ['ASCII', 'UTF-8'];\n    private static $language = 'neutral';\n    private static $internalEncoding = 'UTF-8';\n\n    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)\n    {\n        if (\\is_array($fromEncoding) || ($fromEncoding !== null && false !== strpos($fromEncoding, ','))) {\n            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);\n        } else {\n            $fromEncoding = self::getEncoding($fromEncoding);\n        }\n\n        $toEncoding = self::getEncoding($toEncoding);\n\n        if ('BASE64' === $fromEncoding) {\n            $s = base64_decode($s);\n            $fromEncoding = $toEncoding;\n        }\n\n        if ('BASE64' === $toEncoding) {\n            return base64_encode($s);\n        }\n\n        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {\n            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {\n                $fromEncoding = 'Windows-1252';\n            }\n            if ('UTF-8' !== $fromEncoding) {\n                $s = \\iconv($fromEncoding, 'UTF-8//IGNORE', $s);\n            }\n\n            return preg_replace_callback('/[\\x80-\\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);\n        }\n\n        if ('HTML-ENTITIES' === $fromEncoding) {\n            $s = html_entity_decode($s, \\ENT_COMPAT, 'UTF-8');\n            $fromEncoding = 'UTF-8';\n        }\n\n        return \\iconv($fromEncoding, $toEncoding.'//IGNORE', $s);\n    }\n\n    public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)\n    {\n        $ok = true;\n        array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {\n            if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {\n                $ok = false;\n            }\n        });\n\n        return $ok ? $fromEncoding : false;\n    }\n\n    public static function mb_decode_mimeheader($s)\n    {\n        return \\iconv_mime_decode($s, 2, self::$internalEncoding);\n    }\n\n    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)\n    {\n        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \\E_USER_WARNING);\n    }\n\n    public static function mb_decode_numericentity($s, $convmap, $encoding = null)\n    {\n        if (null !== $s && !is_scalar($s) && !(\\is_object($s) && method_exists($s, '__toString'))) {\n            trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\\gettype($s).' given', \\E_USER_WARNING);\n\n            return null;\n        }\n\n        if (!\\is_array($convmap) || (80000 > \\PHP_VERSION_ID && !$convmap)) {\n            return false;\n        }\n\n        if (null !== $encoding && !is_scalar($encoding)) {\n            trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\\gettype($s).' given', \\E_USER_WARNING);\n\n            return '';  // Instead of null (cf. mb_encode_numericentity).\n        }\n\n        $s = (string) $s;\n        if ('' === $s) {\n            return '';\n        }\n\n        $encoding = self::getEncoding($encoding);\n\n        if ('UTF-8' === $encoding) {\n            $encoding = null;\n            if (!preg_match('//u', $s)) {\n                $s = @\\iconv('UTF-8', 'UTF-8//IGNORE', $s);\n            }\n        } else {\n            $s = \\iconv($encoding, 'UTF-8//IGNORE', $s);\n        }\n\n        $cnt = floor(\\count($convmap) / 4) * 4;\n\n        for ($i = 0; $i < $cnt; $i += 4) {\n            // collector_decode_htmlnumericentity ignores $convmap[$i + 3]\n            $convmap[$i] += $convmap[$i + 2];\n            $convmap[$i + 1] += $convmap[$i + 2];\n        }\n\n        $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {\n            $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];\n            for ($i = 0; $i < $cnt; $i += 4) {\n                if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {\n                    return self::mb_chr($c - $convmap[$i + 2]);\n                }\n            }\n\n            return $m[0];\n        }, $s);\n\n        if (null === $encoding) {\n            return $s;\n        }\n\n        return \\iconv('UTF-8', $encoding.'//IGNORE', $s);\n    }\n\n    public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)\n    {\n        if (null !== $s && !is_scalar($s) && !(\\is_object($s) && method_exists($s, '__toString'))) {\n            trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\\gettype($s).' given', \\E_USER_WARNING);\n\n            return null;\n        }\n\n        if (!\\is_array($convmap) || (80000 > \\PHP_VERSION_ID && !$convmap)) {\n            return false;\n        }\n\n        if (null !== $encoding && !is_scalar($encoding)) {\n            trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\\gettype($s).' given', \\E_USER_WARNING);\n\n            return null;  // Instead of '' (cf. mb_decode_numericentity).\n        }\n\n        if (null !== $is_hex && !is_scalar($is_hex)) {\n            trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\\gettype($s).' given', \\E_USER_WARNING);\n\n            return null;\n        }\n\n        $s = (string) $s;\n        if ('' === $s) {\n            return '';\n        }\n\n        $encoding = self::getEncoding($encoding);\n\n        if ('UTF-8' === $encoding) {\n            $encoding = null;\n            if (!preg_match('//u', $s)) {\n                $s = @\\iconv('UTF-8', 'UTF-8//IGNORE', $s);\n            }\n        } else {\n            $s = \\iconv($encoding, 'UTF-8//IGNORE', $s);\n        }\n\n        static $ulenMask = [\"\\xC0\" => 2, \"\\xD0\" => 2, \"\\xE0\" => 3, \"\\xF0\" => 4];\n\n        $cnt = floor(\\count($convmap) / 4) * 4;\n        $i = 0;\n        $len = \\strlen($s);\n        $result = '';\n\n        while ($i < $len) {\n            $ulen = $s[$i] < \"\\x80\" ? 1 : $ulenMask[$s[$i] & \"\\xF0\"];\n            $uchr = substr($s, $i, $ulen);\n            $i += $ulen;\n            $c = self::mb_ord($uchr);\n\n            for ($j = 0; $j < $cnt; $j += 4) {\n                if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {\n                    $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];\n                    $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';\n                    continue 2;\n                }\n            }\n            $result .= $uchr;\n        }\n\n        if (null === $encoding) {\n            return $result;\n        }\n\n        return \\iconv('UTF-8', $encoding.'//IGNORE', $result);\n    }\n\n    public static function mb_convert_case($s, $mode, $encoding = null)\n    {\n        $s = (string) $s;\n        if ('' === $s) {\n            return '';\n        }\n\n        $encoding = self::getEncoding($encoding);\n\n        if ('UTF-8' === $encoding) {\n            $encoding = null;\n            if (!preg_match('//u', $s)) {\n                $s = @\\iconv('UTF-8', 'UTF-8//IGNORE', $s);\n            }\n        } else {\n            $s = \\iconv($encoding, 'UTF-8//IGNORE', $s);\n        }\n\n        if (\\MB_CASE_TITLE == $mode) {\n            static $titleRegexp = null;\n            if (null === $titleRegexp) {\n                $titleRegexp = self::getData('titleCaseRegexp');\n            }\n            $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);\n        } else {\n            if (\\MB_CASE_UPPER == $mode) {\n                static $upper = null;\n                if (null === $upper) {\n                    $upper = self::getData('upperCase');\n                }\n                $map = $upper;\n            } else {\n                if (self::MB_CASE_FOLD === $mode) {\n                    $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);\n                }\n\n                static $lower = null;\n                if (null === $lower) {\n                    $lower = self::getData('lowerCase');\n                }\n                $map = $lower;\n            }\n\n            static $ulenMask = [\"\\xC0\" => 2, \"\\xD0\" => 2, \"\\xE0\" => 3, \"\\xF0\" => 4];\n\n            $i = 0;\n            $len = \\strlen($s);\n\n            while ($i < $len) {\n                $ulen = $s[$i] < \"\\x80\" ? 1 : $ulenMask[$s[$i] & \"\\xF0\"];\n                $uchr = substr($s, $i, $ulen);\n                $i += $ulen;\n\n                if (isset($map[$uchr])) {\n                    $uchr = $map[$uchr];\n                    $nlen = \\strlen($uchr);\n\n                    if ($nlen == $ulen) {\n                        $nlen = $i;\n                        do {\n                            $s[--$nlen] = $uchr[--$ulen];\n                        } while ($ulen);\n                    } else {\n                        $s = substr_replace($s, $uchr, $i - $ulen, $ulen);\n                        $len += $nlen - $ulen;\n                        $i += $nlen - $ulen;\n                    }\n                }\n            }\n        }\n\n        if (null === $encoding) {\n            return $s;\n        }\n\n        return \\iconv('UTF-8', $encoding.'//IGNORE', $s);\n    }\n\n    public static function mb_internal_encoding($encoding = null)\n    {\n        if (null === $encoding) {\n            return self::$internalEncoding;\n        }\n\n        $normalizedEncoding = self::getEncoding($encoding);\n\n        if ('UTF-8' === $normalizedEncoding || false !== @\\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {\n            self::$internalEncoding = $normalizedEncoding;\n\n            return true;\n        }\n\n        if (80000 > \\PHP_VERSION_ID) {\n            return false;\n        }\n\n        throw new \\ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, \"%s\" given', $encoding));\n    }\n\n    public static function mb_language($lang = null)\n    {\n        if (null === $lang) {\n            return self::$language;\n        }\n\n        switch ($normalizedLang = strtolower($lang)) {\n            case 'uni':\n            case 'neutral':\n                self::$language = $normalizedLang;\n\n                return true;\n        }\n\n        if (80000 > \\PHP_VERSION_ID) {\n            return false;\n        }\n\n        throw new \\ValueError(sprintf('Argument #1 ($language) must be a valid language, \"%s\" given', $lang));\n    }\n\n    public static function mb_list_encodings()\n    {\n        return ['UTF-8'];\n    }\n\n    public static function mb_encoding_aliases($encoding)\n    {\n        switch (strtoupper($encoding)) {\n            case 'UTF8':\n            case 'UTF-8':\n                return ['utf8'];\n        }\n\n        return false;\n    }\n\n    public static function mb_check_encoding($var = null, $encoding = null)\n    {\n        if (null === $encoding) {\n            if (null === $var) {\n                return false;\n            }\n            $encoding = self::$internalEncoding;\n        }\n\n        return self::mb_detect_encoding($var, [$encoding]) || false !== @\\iconv($encoding, $encoding, $var);\n    }\n\n    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)\n    {\n        if (null === $encodingList) {\n            $encodingList = self::$encodingList;\n        } else {\n            if (!\\is_array($encodingList)) {\n                $encodingList = array_map('trim', explode(',', $encodingList));\n            }\n            $encodingList = array_map('strtoupper', $encodingList);\n        }\n\n        foreach ($encodingList as $enc) {\n            switch ($enc) {\n                case 'ASCII':\n                    if (!preg_match('/[\\x80-\\xFF]/', $str)) {\n                        return $enc;\n                    }\n                    break;\n\n                case 'UTF8':\n                case 'UTF-8':\n                    if (preg_match('//u', $str)) {\n                        return 'UTF-8';\n                    }\n                    break;\n\n                default:\n                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {\n                        return $enc;\n                    }\n            }\n        }\n\n        return false;\n    }\n\n    public static function mb_detect_order($encodingList = null)\n    {\n        if (null === $encodingList) {\n            return self::$encodingList;\n        }\n\n        if (!\\is_array($encodingList)) {\n            $encodingList = array_map('trim', explode(',', $encodingList));\n        }\n        $encodingList = array_map('strtoupper', $encodingList);\n\n        foreach ($encodingList as $enc) {\n            switch ($enc) {\n                default:\n                    if (strncmp($enc, 'ISO-8859-', 9)) {\n                        return false;\n                    }\n                    // no break\n                case 'ASCII':\n                case 'UTF8':\n                case 'UTF-8':\n            }\n        }\n\n        self::$encodingList = $encodingList;\n\n        return true;\n    }\n\n    public static function mb_strlen($s, $encoding = null)\n    {\n        $encoding = self::getEncoding($encoding);\n        if ('CP850' === $encoding || 'ASCII' === $encoding) {\n            return \\strlen($s);\n        }\n\n        return @\\iconv_strlen($s, $encoding);\n    }\n\n    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)\n    {\n        $encoding = self::getEncoding($encoding);\n        if ('CP850' === $encoding || 'ASCII' === $encoding) {\n            return strpos($haystack, $needle, $offset);\n        }\n\n        $needle = (string) $needle;\n        if ('' === $needle) {\n            if (80000 > \\PHP_VERSION_ID) {\n                trigger_error(__METHOD__.': Empty delimiter', \\E_USER_WARNING);\n\n                return false;\n            }\n\n            return 0;\n        }\n\n        return \\iconv_strpos($haystack, $needle, $offset, $encoding);\n    }\n\n    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)\n    {\n        $encoding = self::getEncoding($encoding);\n        if ('CP850' === $encoding || 'ASCII' === $encoding) {\n            return strrpos($haystack, $needle, $offset);\n        }\n\n        if ($offset != (int) $offset) {\n            $offset = 0;\n        } elseif ($offset = (int) $offset) {\n            if ($offset < 0) {\n                if (0 > $offset += self::mb_strlen($needle)) {\n                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);\n                }\n                $offset = 0;\n            } else {\n                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);\n            }\n        }\n\n        $pos = '' !== $needle || 80000 > \\PHP_VERSION_ID\n            ? \\iconv_strrpos($haystack, $needle, $encoding)\n            : self::mb_strlen($haystack, $encoding);\n\n        return false !== $pos ? $offset + $pos : false;\n    }\n\n    public static function mb_str_split($string, $split_length = 1, $encoding = null)\n    {\n        if (null !== $string && !is_scalar($string) && !(\\is_object($string) && method_exists($string, '__toString'))) {\n            trigger_error('mb_str_split() expects parameter 1 to be string, '.\\gettype($string).' given', \\E_USER_WARNING);\n\n            return null;\n        }\n\n        if (1 > $split_length = (int) $split_length) {\n            if (80000 > \\PHP_VERSION_ID) {\n                trigger_error('The length of each segment must be greater than zero', \\E_USER_WARNING);\n                return false;\n            }\n\n            throw new \\ValueError('Argument #2 ($length) must be greater than 0');\n        }\n\n        if (null === $encoding) {\n            $encoding = mb_internal_encoding();\n        }\n\n        if ('UTF-8' === $encoding = self::getEncoding($encoding)) {\n            $rx = '/(';\n            while (65535 < $split_length) {\n                $rx .= '.{65535}';\n                $split_length -= 65535;\n            }\n            $rx .= '.{'.$split_length.'})/us';\n\n            return preg_split($rx, $string, null, \\PREG_SPLIT_DELIM_CAPTURE | \\PREG_SPLIT_NO_EMPTY);\n        }\n\n        $result = [];\n        $length = mb_strlen($string, $encoding);\n\n        for ($i = 0; $i < $length; $i += $split_length) {\n            $result[] = mb_substr($string, $i, $split_length, $encoding);\n        }\n\n        return $result;\n    }\n\n    public static function mb_strtolower($s, $encoding = null)\n    {\n        return self::mb_convert_case($s, \\MB_CASE_LOWER, $encoding);\n    }\n\n    public static function mb_strtoupper($s, $encoding = null)\n    {\n        return self::mb_convert_case($s, \\MB_CASE_UPPER, $encoding);\n    }\n\n    public static function mb_substitute_character($c = null)\n    {\n        if (null === $c) {\n            return 'none';\n        }\n        if (0 === strcasecmp($c, 'none')) {\n            return true;\n        }\n        if (80000 > \\PHP_VERSION_ID) {\n            return false;\n        }\n        if (\\is_int($c) || 'long' === $c || 'entity' === $c) {\n            return false;\n        }\n\n        throw new \\ValueError('Argument #1 ($substitute_character) must be \"none\", \"long\", \"entity\" or a valid codepoint');\n    }\n\n    public static function mb_substr($s, $start, $length = null, $encoding = null)\n    {\n        $encoding = self::getEncoding($encoding);\n        if ('CP850' === $encoding || 'ASCII' === $encoding) {\n            return (string) substr($s, $start, null === $length ? 2147483647 : $length);\n        }\n\n        if ($start < 0) {\n            $start = \\iconv_strlen($s, $encoding) + $start;\n            if ($start < 0) {\n                $start = 0;\n            }\n        }\n\n        if (null === $length) {\n            $length = 2147483647;\n        } elseif ($length < 0) {\n            $length = \\iconv_strlen($s, $encoding) + $length - $start;\n            if ($length < 0) {\n                return '';\n            }\n        }\n\n        return (string) \\iconv_substr($s, $start, $length, $encoding);\n    }\n\n    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)\n    {\n        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);\n        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);\n\n        return self::mb_strpos($haystack, $needle, $offset, $encoding);\n    }\n\n    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)\n    {\n        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);\n\n        return self::getSubpart($pos, $part, $haystack, $encoding);\n    }\n\n    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)\n    {\n        $encoding = self::getEncoding($encoding);\n        if ('CP850' === $encoding || 'ASCII' === $encoding) {\n            $pos = strrpos($haystack, $needle);\n        } else {\n            $needle = self::mb_substr($needle, 0, 1, $encoding);\n            $pos = \\iconv_strrpos($haystack, $needle, $encoding);\n        }\n\n        return self::getSubpart($pos, $part, $haystack, $encoding);\n    }\n\n    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)\n    {\n        $needle = self::mb_substr($needle, 0, 1, $encoding);\n        $pos = self::mb_strripos($haystack, $needle, $encoding);\n\n        return self::getSubpart($pos, $part, $haystack, $encoding);\n    }\n\n    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)\n    {\n        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);\n        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);\n\n        return self::mb_strrpos($haystack, $needle, $offset, $encoding);\n    }\n\n    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)\n    {\n        $pos = strpos($haystack, $needle);\n        if (false === $pos) {\n            return false;\n        }\n        if ($part) {\n            return substr($haystack, 0, $pos);\n        }\n\n        return substr($haystack, $pos);\n    }\n\n    public static function mb_get_info($type = 'all')\n    {\n        $info = [\n            'internal_encoding' => self::$internalEncoding,\n            'http_output' => 'pass',\n            'http_output_conv_mimetypes' => '^(text/|application/xhtml\\+xml)',\n            'func_overload' => 0,\n            'func_overload_list' => 'no overload',\n            'mail_charset' => 'UTF-8',\n            'mail_header_encoding' => 'BASE64',\n            'mail_body_encoding' => 'BASE64',\n            'illegal_chars' => 0,\n            'encoding_translation' => 'Off',\n            'language' => self::$language,\n            'detect_order' => self::$encodingList,\n            'substitute_character' => 'none',\n            'strict_detection' => 'Off',\n        ];\n\n        if ('all' === $type) {\n            return $info;\n        }\n        if (isset($info[$type])) {\n            return $info[$type];\n        }\n\n        return false;\n    }\n\n    public static function mb_http_input($type = '')\n    {\n        return false;\n    }\n\n    public static function mb_http_output($encoding = null)\n    {\n        return null !== $encoding ? 'pass' === $encoding : 'pass';\n    }\n\n    public static function mb_strwidth($s, $encoding = null)\n    {\n        $encoding = self::getEncoding($encoding);\n\n        if ('UTF-8' !== $encoding) {\n            $s = \\iconv($encoding, 'UTF-8//IGNORE', $s);\n        }\n\n        $s = preg_replace('/[\\x{1100}-\\x{115F}\\x{2329}\\x{232A}\\x{2E80}-\\x{303E}\\x{3040}-\\x{A4CF}\\x{AC00}-\\x{D7A3}\\x{F900}-\\x{FAFF}\\x{FE10}-\\x{FE19}\\x{FE30}-\\x{FE6F}\\x{FF00}-\\x{FF60}\\x{FFE0}-\\x{FFE6}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}]/u', '', $s, -1, $wide);\n\n        return ($wide << 1) + \\iconv_strlen($s, 'UTF-8');\n    }\n\n    public static function mb_substr_count($haystack, $needle, $encoding = null)\n    {\n        return substr_count($haystack, $needle);\n    }\n\n    public static function mb_output_handler($contents, $status)\n    {\n        return $contents;\n    }\n\n    public static function mb_chr($code, $encoding = null)\n    {\n        if (0x80 > $code %= 0x200000) {\n            $s = \\chr($code);\n        } elseif (0x800 > $code) {\n            $s = \\chr(0xC0 | $code >> 6).\\chr(0x80 | $code & 0x3F);\n        } elseif (0x10000 > $code) {\n            $s = \\chr(0xE0 | $code >> 12).\\chr(0x80 | $code >> 6 & 0x3F).\\chr(0x80 | $code & 0x3F);\n        } else {\n            $s = \\chr(0xF0 | $code >> 18).\\chr(0x80 | $code >> 12 & 0x3F).\\chr(0x80 | $code >> 6 & 0x3F).\\chr(0x80 | $code & 0x3F);\n        }\n\n        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {\n            $s = mb_convert_encoding($s, $encoding, 'UTF-8');\n        }\n\n        return $s;\n    }\n\n    public static function mb_ord($s, $encoding = null)\n    {\n        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {\n            $s = mb_convert_encoding($s, 'UTF-8', $encoding);\n        }\n\n        if (1 === \\strlen($s)) {\n            return \\ord($s);\n        }\n\n        $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;\n        if (0xF0 <= $code) {\n            return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;\n        }\n        if (0xE0 <= $code) {\n            return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;\n        }\n        if (0xC0 <= $code) {\n            return (($code - 0xC0) << 6) + $s[2] - 0x80;\n        }\n\n        return $code;\n    }\n\n    private static function getSubpart($pos, $part, $haystack, $encoding)\n    {\n        if (false === $pos) {\n            return false;\n        }\n        if ($part) {\n            return self::mb_substr($haystack, 0, $pos, $encoding);\n        }\n\n        return self::mb_substr($haystack, $pos, null, $encoding);\n    }\n\n    private static function html_encoding_callback(array $m)\n    {\n        $i = 1;\n        $entities = '';\n        $m = unpack('C*', htmlentities($m[0], \\ENT_COMPAT, 'UTF-8'));\n\n        while (isset($m[$i])) {\n            if (0x80 > $m[$i]) {\n                $entities .= \\chr($m[$i++]);\n                continue;\n            }\n            if (0xF0 <= $m[$i]) {\n                $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;\n            } elseif (0xE0 <= $m[$i]) {\n                $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;\n            } else {\n                $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;\n            }\n\n            $entities .= '&#'.$c.';';\n        }\n\n        return $entities;\n    }\n\n    private static function title_case(array $s)\n    {\n        return self::mb_convert_case($s[1], \\MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \\MB_CASE_LOWER, 'UTF-8');\n    }\n\n    private static function getData($file)\n    {\n        if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {\n            return require $file;\n        }\n\n        return false;\n    }\n\n    private static function getEncoding($encoding)\n    {\n        if (null === $encoding) {\n            return self::$internalEncoding;\n        }\n\n        if ('UTF-8' === $encoding) {\n            return 'UTF-8';\n        }\n\n        $encoding = strtoupper($encoding);\n\n        if ('8BIT' === $encoding || 'BINARY' === $encoding) {\n            return 'CP850';\n        }\n\n        if ('UTF8' === $encoding) {\n            return 'UTF-8';\n        }\n\n        return $encoding;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/README.md",
    "content": "Symfony Polyfill / Mbstring\n===========================\n\nThis component provides a partial, native PHP implementation for the\n[Mbstring](https://php.net/mbstring) extension.\n\nMore information can be found in the\n[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).\n\nLicense\n=======\n\nThis library is released under the [MIT license](LICENSE).\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php",
    "content": "<?php\n\nreturn array (\n  'A' => 'a',\n  'B' => 'b',\n  'C' => 'c',\n  'D' => 'd',\n  'E' => 'e',\n  'F' => 'f',\n  'G' => 'g',\n  'H' => 'h',\n  'I' => 'i',\n  'J' => 'j',\n  'K' => 'k',\n  'L' => 'l',\n  'M' => 'm',\n  'N' => 'n',\n  'O' => 'o',\n  'P' => 'p',\n  'Q' => 'q',\n  'R' => 'r',\n  'S' => 's',\n  'T' => 't',\n  'U' => 'u',\n  'V' => 'v',\n  'W' => 'w',\n  'X' => 'x',\n  'Y' => 'y',\n  'Z' => 'z',\n  'À' => 'à',\n  'Á' => 'á',\n  'Â' => 'â',\n  'Ã' => 'ã',\n  'Ä' => 'ä',\n  'Å' => 'å',\n  'Æ' => 'æ',\n  'Ç' => 'ç',\n  'È' => 'è',\n  'É' => 'é',\n  'Ê' => 'ê',\n  'Ë' => 'ë',\n  'Ì' => 'ì',\n  'Í' => 'í',\n  'Î' => 'î',\n  'Ï' => 'ï',\n  'Ð' => 'ð',\n  'Ñ' => 'ñ',\n  'Ò' => 'ò',\n  'Ó' => 'ó',\n  'Ô' => 'ô',\n  'Õ' => 'õ',\n  'Ö' => 'ö',\n  'Ø' => 'ø',\n  'Ù' => 'ù',\n  'Ú' => 'ú',\n  'Û' => 'û',\n  'Ü' => 'ü',\n  'Ý' => 'ý',\n  'Þ' => 'þ',\n  'Ā' => 'ā',\n  'Ă' => 'ă',\n  'Ą' => 'ą',\n  'Ć' => 'ć',\n  'Ĉ' => 'ĉ',\n  'Ċ' => 'ċ',\n  'Č' => 'č',\n  'Ď' => 'ď',\n  'Đ' => 'đ',\n  'Ē' => 'ē',\n  'Ĕ' => 'ĕ',\n  'Ė' => 'ė',\n  'Ę' => 'ę',\n  'Ě' => 'ě',\n  'Ĝ' => 'ĝ',\n  'Ğ' => 'ğ',\n  'Ġ' => 'ġ',\n  'Ģ' => 'ģ',\n  'Ĥ' => 'ĥ',\n  'Ħ' => 'ħ',\n  'Ĩ' => 'ĩ',\n  'Ī' => 'ī',\n  'Ĭ' => 'ĭ',\n  'Į' => 'į',\n  'İ' => 'i̇',\n  'Ĳ' => 'ĳ',\n  'Ĵ' => 'ĵ',\n  'Ķ' => 'ķ',\n  'Ĺ' => 'ĺ',\n  'Ļ' => 'ļ',\n  'Ľ' => 'ľ',\n  'Ŀ' => 'ŀ',\n  'Ł' => 'ł',\n  'Ń' => 'ń',\n  'Ņ' => 'ņ',\n  'Ň' => 'ň',\n  'Ŋ' => 'ŋ',\n  'Ō' => 'ō',\n  'Ŏ' => 'ŏ',\n  'Ő' => 'ő',\n  'Œ' => 'œ',\n  'Ŕ' => 'ŕ',\n  'Ŗ' => 'ŗ',\n  'Ř' => 'ř',\n  'Ś' => 'ś',\n  'Ŝ' => 'ŝ',\n  'Ş' => 'ş',\n  'Š' => 'š',\n  'Ţ' => 'ţ',\n  'Ť' => 'ť',\n  'Ŧ' => 'ŧ',\n  'Ũ' => 'ũ',\n  'Ū' => 'ū',\n  'Ŭ' => 'ŭ',\n  'Ů' => 'ů',\n  'Ű' => 'ű',\n  'Ų' => 'ų',\n  'Ŵ' => 'ŵ',\n  'Ŷ' => 'ŷ',\n  'Ÿ' => 'ÿ',\n  'Ź' => 'ź',\n  'Ż' => 'ż',\n  'Ž' => 'ž',\n  'Ɓ' => 'ɓ',\n  'Ƃ' => 'ƃ',\n  'Ƅ' => 'ƅ',\n  'Ɔ' => 'ɔ',\n  'Ƈ' => 'ƈ',\n  'Ɖ' => 'ɖ',\n  'Ɗ' => 'ɗ',\n  'Ƌ' => 'ƌ',\n  'Ǝ' => 'ǝ',\n  'Ə' => 'ə',\n  'Ɛ' => 'ɛ',\n  'Ƒ' => 'ƒ',\n  'Ɠ' => 'ɠ',\n  'Ɣ' => 'ɣ',\n  'Ɩ' => 'ɩ',\n  'Ɨ' => 'ɨ',\n  'Ƙ' => 'ƙ',\n  'Ɯ' => 'ɯ',\n  'Ɲ' => 'ɲ',\n  'Ɵ' => 'ɵ',\n  'Ơ' => 'ơ',\n  'Ƣ' => 'ƣ',\n  'Ƥ' => 'ƥ',\n  'Ʀ' => 'ʀ',\n  'Ƨ' => 'ƨ',\n  'Ʃ' => 'ʃ',\n  'Ƭ' => 'ƭ',\n  'Ʈ' => 'ʈ',\n  'Ư' => 'ư',\n  'Ʊ' => 'ʊ',\n  'Ʋ' => 'ʋ',\n  'Ƴ' => 'ƴ',\n  'Ƶ' => 'ƶ',\n  'Ʒ' => 'ʒ',\n  'Ƹ' => 'ƹ',\n  'Ƽ' => 'ƽ',\n  'Ǆ' => 'ǆ',\n  'ǅ' => 'ǆ',\n  'Ǉ' => 'ǉ',\n  'ǈ' => 'ǉ',\n  'Ǌ' => 'ǌ',\n  'ǋ' => 'ǌ',\n  'Ǎ' => 'ǎ',\n  'Ǐ' => 'ǐ',\n  'Ǒ' => 'ǒ',\n  'Ǔ' => 'ǔ',\n  'Ǖ' => 'ǖ',\n  'Ǘ' => 'ǘ',\n  'Ǚ' => 'ǚ',\n  'Ǜ' => 'ǜ',\n  'Ǟ' => 'ǟ',\n  'Ǡ' => 'ǡ',\n  'Ǣ' => 'ǣ',\n  'Ǥ' => 'ǥ',\n  'Ǧ' => 'ǧ',\n  'Ǩ' => 'ǩ',\n  'Ǫ' => 'ǫ',\n  'Ǭ' => 'ǭ',\n  'Ǯ' => 'ǯ',\n  'Ǳ' => 'ǳ',\n  'ǲ' => 'ǳ',\n  'Ǵ' => 'ǵ',\n  'Ƕ' => 'ƕ',\n  'Ƿ' => 'ƿ',\n  'Ǹ' => 'ǹ',\n  'Ǻ' => 'ǻ',\n  'Ǽ' => 'ǽ',\n  'Ǿ' => 'ǿ',\n  'Ȁ' => 'ȁ',\n  'Ȃ' => 'ȃ',\n  'Ȅ' => 'ȅ',\n  'Ȇ' => 'ȇ',\n  'Ȉ' => 'ȉ',\n  'Ȋ' => 'ȋ',\n  'Ȍ' => 'ȍ',\n  'Ȏ' => 'ȏ',\n  'Ȑ' => 'ȑ',\n  'Ȓ' => 'ȓ',\n  'Ȕ' => 'ȕ',\n  'Ȗ' => 'ȗ',\n  'Ș' => 'ș',\n  'Ț' => 'ț',\n  'Ȝ' => 'ȝ',\n  'Ȟ' => 'ȟ',\n  'Ƞ' => 'ƞ',\n  'Ȣ' => 'ȣ',\n  'Ȥ' => 'ȥ',\n  'Ȧ' => 'ȧ',\n  'Ȩ' => 'ȩ',\n  'Ȫ' => 'ȫ',\n  'Ȭ' => 'ȭ',\n  'Ȯ' => 'ȯ',\n  'Ȱ' => 'ȱ',\n  'Ȳ' => 'ȳ',\n  'Ⱥ' => 'ⱥ',\n  'Ȼ' => 'ȼ',\n  'Ƚ' => 'ƚ',\n  'Ⱦ' => 'ⱦ',\n  'Ɂ' => 'ɂ',\n  'Ƀ' => 'ƀ',\n  'Ʉ' => 'ʉ',\n  'Ʌ' => 'ʌ',\n  'Ɇ' => 'ɇ',\n  'Ɉ' => 'ɉ',\n  'Ɋ' => 'ɋ',\n  'Ɍ' => 'ɍ',\n  'Ɏ' => 'ɏ',\n  'Ͱ' => 'ͱ',\n  'Ͳ' => 'ͳ',\n  'Ͷ' => 'ͷ',\n  'Ϳ' => 'ϳ',\n  'Ά' => 'ά',\n  'Έ' => 'έ',\n  'Ή' => 'ή',\n  'Ί' => 'ί',\n  'Ό' => 'ό',\n  'Ύ' => 'ύ',\n  'Ώ' => 'ώ',\n  'Α' => 'α',\n  'Β' => 'β',\n  'Γ' => 'γ',\n  'Δ' => 'δ',\n  'Ε' => 'ε',\n  'Ζ' => 'ζ',\n  'Η' => 'η',\n  'Θ' => 'θ',\n  'Ι' => 'ι',\n  'Κ' => 'κ',\n  'Λ' => 'λ',\n  'Μ' => 'μ',\n  'Ν' => 'ν',\n  'Ξ' => 'ξ',\n  'Ο' => 'ο',\n  'Π' => 'π',\n  'Ρ' => 'ρ',\n  'Σ' => 'σ',\n  'Τ' => 'τ',\n  'Υ' => 'υ',\n  'Φ' => 'φ',\n  'Χ' => 'χ',\n  'Ψ' => 'ψ',\n  'Ω' => 'ω',\n  'Ϊ' => 'ϊ',\n  'Ϋ' => 'ϋ',\n  'Ϗ' => 'ϗ',\n  'Ϙ' => 'ϙ',\n  'Ϛ' => 'ϛ',\n  'Ϝ' => 'ϝ',\n  'Ϟ' => 'ϟ',\n  'Ϡ' => 'ϡ',\n  'Ϣ' => 'ϣ',\n  'Ϥ' => 'ϥ',\n  'Ϧ' => 'ϧ',\n  'Ϩ' => 'ϩ',\n  'Ϫ' => 'ϫ',\n  'Ϭ' => 'ϭ',\n  'Ϯ' => 'ϯ',\n  'ϴ' => 'θ',\n  'Ϸ' => 'ϸ',\n  'Ϲ' => 'ϲ',\n  'Ϻ' => 'ϻ',\n  'Ͻ' => 'ͻ',\n  'Ͼ' => 'ͼ',\n  'Ͽ' => 'ͽ',\n  'Ѐ' => 'ѐ',\n  'Ё' => 'ё',\n  'Ђ' => 'ђ',\n  'Ѓ' => 'ѓ',\n  'Є' => 'є',\n  'Ѕ' => 'ѕ',\n  'І' => 'і',\n  'Ї' => 'ї',\n  'Ј' => 'ј',\n  'Љ' => 'љ',\n  'Њ' => 'њ',\n  'Ћ' => 'ћ',\n  'Ќ' => 'ќ',\n  'Ѝ' => 'ѝ',\n  'Ў' => 'ў',\n  'Џ' => 'џ',\n  'А' => 'а',\n  'Б' => 'б',\n  'В' => 'в',\n  'Г' => 'г',\n  'Д' => 'д',\n  'Е' => 'е',\n  'Ж' => 'ж',\n  'З' => 'з',\n  'И' => 'и',\n  'Й' => 'й',\n  'К' => 'к',\n  'Л' => 'л',\n  'М' => 'м',\n  'Н' => 'н',\n  'О' => 'о',\n  'П' => 'п',\n  'Р' => 'р',\n  'С' => 'с',\n  'Т' => 'т',\n  'У' => 'у',\n  'Ф' => 'ф',\n  'Х' => 'х',\n  'Ц' => 'ц',\n  'Ч' => 'ч',\n  'Ш' => 'ш',\n  'Щ' => 'щ',\n  'Ъ' => 'ъ',\n  'Ы' => 'ы',\n  'Ь' => 'ь',\n  'Э' => 'э',\n  'Ю' => 'ю',\n  'Я' => 'я',\n  'Ѡ' => 'ѡ',\n  'Ѣ' => 'ѣ',\n  'Ѥ' => 'ѥ',\n  'Ѧ' => 'ѧ',\n  'Ѩ' => 'ѩ',\n  'Ѫ' => 'ѫ',\n  'Ѭ' => 'ѭ',\n  'Ѯ' => 'ѯ',\n  'Ѱ' => 'ѱ',\n  'Ѳ' => 'ѳ',\n  'Ѵ' => 'ѵ',\n  'Ѷ' => 'ѷ',\n  'Ѹ' => 'ѹ',\n  'Ѻ' => 'ѻ',\n  'Ѽ' => 'ѽ',\n  'Ѿ' => 'ѿ',\n  'Ҁ' => 'ҁ',\n  'Ҋ' => 'ҋ',\n  'Ҍ' => 'ҍ',\n  'Ҏ' => 'ҏ',\n  'Ґ' => 'ґ',\n  'Ғ' => 'ғ',\n  'Ҕ' => 'ҕ',\n  'Җ' => 'җ',\n  'Ҙ' => 'ҙ',\n  'Қ' => 'қ',\n  'Ҝ' => 'ҝ',\n  'Ҟ' => 'ҟ',\n  'Ҡ' => 'ҡ',\n  'Ң' => 'ң',\n  'Ҥ' => 'ҥ',\n  'Ҧ' => 'ҧ',\n  'Ҩ' => 'ҩ',\n  'Ҫ' => 'ҫ',\n  'Ҭ' => 'ҭ',\n  'Ү' => 'ү',\n  'Ұ' => 'ұ',\n  'Ҳ' => 'ҳ',\n  'Ҵ' => 'ҵ',\n  'Ҷ' => 'ҷ',\n  'Ҹ' => 'ҹ',\n  'Һ' => 'һ',\n  'Ҽ' => 'ҽ',\n  'Ҿ' => 'ҿ',\n  'Ӏ' => 'ӏ',\n  'Ӂ' => 'ӂ',\n  'Ӄ' => 'ӄ',\n  'Ӆ' => 'ӆ',\n  'Ӈ' => 'ӈ',\n  'Ӊ' => 'ӊ',\n  'Ӌ' => 'ӌ',\n  'Ӎ' => 'ӎ',\n  'Ӑ' => 'ӑ',\n  'Ӓ' => 'ӓ',\n  'Ӕ' => 'ӕ',\n  'Ӗ' => 'ӗ',\n  'Ә' => 'ә',\n  'Ӛ' => 'ӛ',\n  'Ӝ' => 'ӝ',\n  'Ӟ' => 'ӟ',\n  'Ӡ' => 'ӡ',\n  'Ӣ' => 'ӣ',\n  'Ӥ' => 'ӥ',\n  'Ӧ' => 'ӧ',\n  'Ө' => 'ө',\n  'Ӫ' => 'ӫ',\n  'Ӭ' => 'ӭ',\n  'Ӯ' => 'ӯ',\n  'Ӱ' => 'ӱ',\n  'Ӳ' => 'ӳ',\n  'Ӵ' => 'ӵ',\n  'Ӷ' => 'ӷ',\n  'Ӹ' => 'ӹ',\n  'Ӻ' => 'ӻ',\n  'Ӽ' => 'ӽ',\n  'Ӿ' => 'ӿ',\n  'Ԁ' => 'ԁ',\n  'Ԃ' => 'ԃ',\n  'Ԅ' => 'ԅ',\n  'Ԇ' => 'ԇ',\n  'Ԉ' => 'ԉ',\n  'Ԋ' => 'ԋ',\n  'Ԍ' => 'ԍ',\n  'Ԏ' => 'ԏ',\n  'Ԑ' => 'ԑ',\n  'Ԓ' => 'ԓ',\n  'Ԕ' => 'ԕ',\n  'Ԗ' => 'ԗ',\n  'Ԙ' => 'ԙ',\n  'Ԛ' => 'ԛ',\n  'Ԝ' => 'ԝ',\n  'Ԟ' => 'ԟ',\n  'Ԡ' => 'ԡ',\n  'Ԣ' => 'ԣ',\n  'Ԥ' => 'ԥ',\n  'Ԧ' => 'ԧ',\n  'Ԩ' => 'ԩ',\n  'Ԫ' => 'ԫ',\n  'Ԭ' => 'ԭ',\n  'Ԯ' => 'ԯ',\n  'Ա' => 'ա',\n  'Բ' => 'բ',\n  'Գ' => 'գ',\n  'Դ' => 'դ',\n  'Ե' => 'ե',\n  'Զ' => 'զ',\n  'Է' => 'է',\n  'Ը' => 'ը',\n  'Թ' => 'թ',\n  'Ժ' => 'ժ',\n  'Ի' => 'ի',\n  'Լ' => 'լ',\n  'Խ' => 'խ',\n  'Ծ' => 'ծ',\n  'Կ' => 'կ',\n  'Հ' => 'հ',\n  'Ձ' => 'ձ',\n  'Ղ' => 'ղ',\n  'Ճ' => 'ճ',\n  'Մ' => 'մ',\n  'Յ' => 'յ',\n  'Ն' => 'ն',\n  'Շ' => 'շ',\n  'Ո' => 'ո',\n  'Չ' => 'չ',\n  'Պ' => 'պ',\n  'Ջ' => 'ջ',\n  'Ռ' => 'ռ',\n  'Ս' => 'ս',\n  'Վ' => 'վ',\n  'Տ' => 'տ',\n  'Ր' => 'ր',\n  'Ց' => 'ց',\n  'Ւ' => 'ւ',\n  'Փ' => 'փ',\n  'Ք' => 'ք',\n  'Օ' => 'օ',\n  'Ֆ' => 'ֆ',\n  'Ⴀ' => 'ⴀ',\n  'Ⴁ' => 'ⴁ',\n  'Ⴂ' => 'ⴂ',\n  'Ⴃ' => 'ⴃ',\n  'Ⴄ' => 'ⴄ',\n  'Ⴅ' => 'ⴅ',\n  'Ⴆ' => 'ⴆ',\n  'Ⴇ' => 'ⴇ',\n  'Ⴈ' => 'ⴈ',\n  'Ⴉ' => 'ⴉ',\n  'Ⴊ' => 'ⴊ',\n  'Ⴋ' => 'ⴋ',\n  'Ⴌ' => 'ⴌ',\n  'Ⴍ' => 'ⴍ',\n  'Ⴎ' => 'ⴎ',\n  'Ⴏ' => 'ⴏ',\n  'Ⴐ' => 'ⴐ',\n  'Ⴑ' => 'ⴑ',\n  'Ⴒ' => 'ⴒ',\n  'Ⴓ' => 'ⴓ',\n  'Ⴔ' => 'ⴔ',\n  'Ⴕ' => 'ⴕ',\n  'Ⴖ' => 'ⴖ',\n  'Ⴗ' => 'ⴗ',\n  'Ⴘ' => 'ⴘ',\n  'Ⴙ' => 'ⴙ',\n  'Ⴚ' => 'ⴚ',\n  'Ⴛ' => 'ⴛ',\n  'Ⴜ' => 'ⴜ',\n  'Ⴝ' => 'ⴝ',\n  'Ⴞ' => 'ⴞ',\n  'Ⴟ' => 'ⴟ',\n  'Ⴠ' => 'ⴠ',\n  'Ⴡ' => 'ⴡ',\n  'Ⴢ' => 'ⴢ',\n  'Ⴣ' => 'ⴣ',\n  'Ⴤ' => 'ⴤ',\n  'Ⴥ' => 'ⴥ',\n  'Ⴧ' => 'ⴧ',\n  'Ⴭ' => 'ⴭ',\n  'Ꭰ' => 'ꭰ',\n  'Ꭱ' => 'ꭱ',\n  'Ꭲ' => 'ꭲ',\n  'Ꭳ' => 'ꭳ',\n  'Ꭴ' => 'ꭴ',\n  'Ꭵ' => 'ꭵ',\n  'Ꭶ' => 'ꭶ',\n  'Ꭷ' => 'ꭷ',\n  'Ꭸ' => 'ꭸ',\n  'Ꭹ' => 'ꭹ',\n  'Ꭺ' => 'ꭺ',\n  'Ꭻ' => 'ꭻ',\n  'Ꭼ' => 'ꭼ',\n  'Ꭽ' => 'ꭽ',\n  'Ꭾ' => 'ꭾ',\n  'Ꭿ' => 'ꭿ',\n  'Ꮀ' => 'ꮀ',\n  'Ꮁ' => 'ꮁ',\n  'Ꮂ' => 'ꮂ',\n  'Ꮃ' => 'ꮃ',\n  'Ꮄ' => 'ꮄ',\n  'Ꮅ' => 'ꮅ',\n  'Ꮆ' => 'ꮆ',\n  'Ꮇ' => 'ꮇ',\n  'Ꮈ' => 'ꮈ',\n  'Ꮉ' => 'ꮉ',\n  'Ꮊ' => 'ꮊ',\n  'Ꮋ' => 'ꮋ',\n  'Ꮌ' => 'ꮌ',\n  'Ꮍ' => 'ꮍ',\n  'Ꮎ' => 'ꮎ',\n  'Ꮏ' => 'ꮏ',\n  'Ꮐ' => 'ꮐ',\n  'Ꮑ' => 'ꮑ',\n  'Ꮒ' => 'ꮒ',\n  'Ꮓ' => 'ꮓ',\n  'Ꮔ' => 'ꮔ',\n  'Ꮕ' => 'ꮕ',\n  'Ꮖ' => 'ꮖ',\n  'Ꮗ' => 'ꮗ',\n  'Ꮘ' => 'ꮘ',\n  'Ꮙ' => 'ꮙ',\n  'Ꮚ' => 'ꮚ',\n  'Ꮛ' => 'ꮛ',\n  'Ꮜ' => 'ꮜ',\n  'Ꮝ' => 'ꮝ',\n  'Ꮞ' => 'ꮞ',\n  'Ꮟ' => 'ꮟ',\n  'Ꮠ' => 'ꮠ',\n  'Ꮡ' => 'ꮡ',\n  'Ꮢ' => 'ꮢ',\n  'Ꮣ' => 'ꮣ',\n  'Ꮤ' => 'ꮤ',\n  'Ꮥ' => 'ꮥ',\n  'Ꮦ' => 'ꮦ',\n  'Ꮧ' => 'ꮧ',\n  'Ꮨ' => 'ꮨ',\n  'Ꮩ' => 'ꮩ',\n  'Ꮪ' => 'ꮪ',\n  'Ꮫ' => 'ꮫ',\n  'Ꮬ' => 'ꮬ',\n  'Ꮭ' => 'ꮭ',\n  'Ꮮ' => 'ꮮ',\n  'Ꮯ' => 'ꮯ',\n  'Ꮰ' => 'ꮰ',\n  'Ꮱ' => 'ꮱ',\n  'Ꮲ' => 'ꮲ',\n  'Ꮳ' => 'ꮳ',\n  'Ꮴ' => 'ꮴ',\n  'Ꮵ' => 'ꮵ',\n  'Ꮶ' => 'ꮶ',\n  'Ꮷ' => 'ꮷ',\n  'Ꮸ' => 'ꮸ',\n  'Ꮹ' => 'ꮹ',\n  'Ꮺ' => 'ꮺ',\n  'Ꮻ' => 'ꮻ',\n  'Ꮼ' => 'ꮼ',\n  'Ꮽ' => 'ꮽ',\n  'Ꮾ' => 'ꮾ',\n  'Ꮿ' => 'ꮿ',\n  'Ᏸ' => 'ᏸ',\n  'Ᏹ' => 'ᏹ',\n  'Ᏺ' => 'ᏺ',\n  'Ᏻ' => 'ᏻ',\n  'Ᏼ' => 'ᏼ',\n  'Ᏽ' => 'ᏽ',\n  'Ა' => 'ა',\n  'Ბ' => 'ბ',\n  'Გ' => 'გ',\n  'Დ' => 'დ',\n  'Ე' => 'ე',\n  'Ვ' => 'ვ',\n  'Ზ' => 'ზ',\n  'Თ' => 'თ',\n  'Ი' => 'ი',\n  'Კ' => 'კ',\n  'Ლ' => 'ლ',\n  'Მ' => 'მ',\n  'Ნ' => 'ნ',\n  'Ო' => 'ო',\n  'Პ' => 'პ',\n  'Ჟ' => 'ჟ',\n  'Რ' => 'რ',\n  'Ს' => 'ს',\n  'Ტ' => 'ტ',\n  'Უ' => 'უ',\n  'Ფ' => 'ფ',\n  'Ქ' => 'ქ',\n  'Ღ' => 'ღ',\n  'Ყ' => 'ყ',\n  'Შ' => 'შ',\n  'Ჩ' => 'ჩ',\n  'Ც' => 'ც',\n  'Ძ' => 'ძ',\n  'Წ' => 'წ',\n  'Ჭ' => 'ჭ',\n  'Ხ' => 'ხ',\n  'Ჯ' => 'ჯ',\n  'Ჰ' => 'ჰ',\n  'Ჱ' => 'ჱ',\n  'Ჲ' => 'ჲ',\n  'Ჳ' => 'ჳ',\n  'Ჴ' => 'ჴ',\n  'Ჵ' => 'ჵ',\n  'Ჶ' => 'ჶ',\n  'Ჷ' => 'ჷ',\n  'Ჸ' => 'ჸ',\n  'Ჹ' => 'ჹ',\n  'Ჺ' => 'ჺ',\n  'Ჽ' => 'ჽ',\n  'Ჾ' => 'ჾ',\n  'Ჿ' => 'ჿ',\n  'Ḁ' => 'ḁ',\n  'Ḃ' => 'ḃ',\n  'Ḅ' => 'ḅ',\n  'Ḇ' => 'ḇ',\n  'Ḉ' => 'ḉ',\n  'Ḋ' => 'ḋ',\n  'Ḍ' => 'ḍ',\n  'Ḏ' => 'ḏ',\n  'Ḑ' => 'ḑ',\n  'Ḓ' => 'ḓ',\n  'Ḕ' => 'ḕ',\n  'Ḗ' => 'ḗ',\n  'Ḙ' => 'ḙ',\n  'Ḛ' => 'ḛ',\n  'Ḝ' => 'ḝ',\n  'Ḟ' => 'ḟ',\n  'Ḡ' => 'ḡ',\n  'Ḣ' => 'ḣ',\n  'Ḥ' => 'ḥ',\n  'Ḧ' => 'ḧ',\n  'Ḩ' => 'ḩ',\n  'Ḫ' => 'ḫ',\n  'Ḭ' => 'ḭ',\n  'Ḯ' => 'ḯ',\n  'Ḱ' => 'ḱ',\n  'Ḳ' => 'ḳ',\n  'Ḵ' => 'ḵ',\n  'Ḷ' => 'ḷ',\n  'Ḹ' => 'ḹ',\n  'Ḻ' => 'ḻ',\n  'Ḽ' => 'ḽ',\n  'Ḿ' => 'ḿ',\n  'Ṁ' => 'ṁ',\n  'Ṃ' => 'ṃ',\n  'Ṅ' => 'ṅ',\n  'Ṇ' => 'ṇ',\n  'Ṉ' => 'ṉ',\n  'Ṋ' => 'ṋ',\n  'Ṍ' => 'ṍ',\n  'Ṏ' => 'ṏ',\n  'Ṑ' => 'ṑ',\n  'Ṓ' => 'ṓ',\n  'Ṕ' => 'ṕ',\n  'Ṗ' => 'ṗ',\n  'Ṙ' => 'ṙ',\n  'Ṛ' => 'ṛ',\n  'Ṝ' => 'ṝ',\n  'Ṟ' => 'ṟ',\n  'Ṡ' => 'ṡ',\n  'Ṣ' => 'ṣ',\n  'Ṥ' => 'ṥ',\n  'Ṧ' => 'ṧ',\n  'Ṩ' => 'ṩ',\n  'Ṫ' => 'ṫ',\n  'Ṭ' => 'ṭ',\n  'Ṯ' => 'ṯ',\n  'Ṱ' => 'ṱ',\n  'Ṳ' => 'ṳ',\n  'Ṵ' => 'ṵ',\n  'Ṷ' => 'ṷ',\n  'Ṹ' => 'ṹ',\n  'Ṻ' => 'ṻ',\n  'Ṽ' => 'ṽ',\n  'Ṿ' => 'ṿ',\n  'Ẁ' => 'ẁ',\n  'Ẃ' => 'ẃ',\n  'Ẅ' => 'ẅ',\n  'Ẇ' => 'ẇ',\n  'Ẉ' => 'ẉ',\n  'Ẋ' => 'ẋ',\n  'Ẍ' => 'ẍ',\n  'Ẏ' => 'ẏ',\n  'Ẑ' => 'ẑ',\n  'Ẓ' => 'ẓ',\n  'Ẕ' => 'ẕ',\n  'ẞ' => 'ß',\n  'Ạ' => 'ạ',\n  'Ả' => 'ả',\n  'Ấ' => 'ấ',\n  'Ầ' => 'ầ',\n  'Ẩ' => 'ẩ',\n  'Ẫ' => 'ẫ',\n  'Ậ' => 'ậ',\n  'Ắ' => 'ắ',\n  'Ằ' => 'ằ',\n  'Ẳ' => 'ẳ',\n  'Ẵ' => 'ẵ',\n  'Ặ' => 'ặ',\n  'Ẹ' => 'ẹ',\n  'Ẻ' => 'ẻ',\n  'Ẽ' => 'ẽ',\n  'Ế' => 'ế',\n  'Ề' => 'ề',\n  'Ể' => 'ể',\n  'Ễ' => 'ễ',\n  'Ệ' => 'ệ',\n  'Ỉ' => 'ỉ',\n  'Ị' => 'ị',\n  'Ọ' => 'ọ',\n  'Ỏ' => 'ỏ',\n  'Ố' => 'ố',\n  'Ồ' => 'ồ',\n  'Ổ' => 'ổ',\n  'Ỗ' => 'ỗ',\n  'Ộ' => 'ộ',\n  'Ớ' => 'ớ',\n  'Ờ' => 'ờ',\n  'Ở' => 'ở',\n  'Ỡ' => 'ỡ',\n  'Ợ' => 'ợ',\n  'Ụ' => 'ụ',\n  'Ủ' => 'ủ',\n  'Ứ' => 'ứ',\n  'Ừ' => 'ừ',\n  'Ử' => 'ử',\n  'Ữ' => 'ữ',\n  'Ự' => 'ự',\n  'Ỳ' => 'ỳ',\n  'Ỵ' => 'ỵ',\n  'Ỷ' => 'ỷ',\n  'Ỹ' => 'ỹ',\n  'Ỻ' => 'ỻ',\n  'Ỽ' => 'ỽ',\n  'Ỿ' => 'ỿ',\n  'Ἀ' => 'ἀ',\n  'Ἁ' => 'ἁ',\n  'Ἂ' => 'ἂ',\n  'Ἃ' => 'ἃ',\n  'Ἄ' => 'ἄ',\n  'Ἅ' => 'ἅ',\n  'Ἆ' => 'ἆ',\n  'Ἇ' => 'ἇ',\n  'Ἐ' => 'ἐ',\n  'Ἑ' => 'ἑ',\n  'Ἒ' => 'ἒ',\n  'Ἓ' => 'ἓ',\n  'Ἔ' => 'ἔ',\n  'Ἕ' => 'ἕ',\n  'Ἠ' => 'ἠ',\n  'Ἡ' => 'ἡ',\n  'Ἢ' => 'ἢ',\n  'Ἣ' => 'ἣ',\n  'Ἤ' => 'ἤ',\n  'Ἥ' => 'ἥ',\n  'Ἦ' => 'ἦ',\n  'Ἧ' => 'ἧ',\n  'Ἰ' => 'ἰ',\n  'Ἱ' => 'ἱ',\n  'Ἲ' => 'ἲ',\n  'Ἳ' => 'ἳ',\n  'Ἴ' => 'ἴ',\n  'Ἵ' => 'ἵ',\n  'Ἶ' => 'ἶ',\n  'Ἷ' => 'ἷ',\n  'Ὀ' => 'ὀ',\n  'Ὁ' => 'ὁ',\n  'Ὂ' => 'ὂ',\n  'Ὃ' => 'ὃ',\n  'Ὄ' => 'ὄ',\n  'Ὅ' => 'ὅ',\n  'Ὑ' => 'ὑ',\n  'Ὓ' => 'ὓ',\n  'Ὕ' => 'ὕ',\n  'Ὗ' => 'ὗ',\n  'Ὠ' => 'ὠ',\n  'Ὡ' => 'ὡ',\n  'Ὢ' => 'ὢ',\n  'Ὣ' => 'ὣ',\n  'Ὤ' => 'ὤ',\n  'Ὥ' => 'ὥ',\n  'Ὦ' => 'ὦ',\n  'Ὧ' => 'ὧ',\n  'ᾈ' => 'ᾀ',\n  'ᾉ' => 'ᾁ',\n  'ᾊ' => 'ᾂ',\n  'ᾋ' => 'ᾃ',\n  'ᾌ' => 'ᾄ',\n  'ᾍ' => 'ᾅ',\n  'ᾎ' => 'ᾆ',\n  'ᾏ' => 'ᾇ',\n  'ᾘ' => 'ᾐ',\n  'ᾙ' => 'ᾑ',\n  'ᾚ' => 'ᾒ',\n  'ᾛ' => 'ᾓ',\n  'ᾜ' => 'ᾔ',\n  'ᾝ' => 'ᾕ',\n  'ᾞ' => 'ᾖ',\n  'ᾟ' => 'ᾗ',\n  'ᾨ' => 'ᾠ',\n  'ᾩ' => 'ᾡ',\n  'ᾪ' => 'ᾢ',\n  'ᾫ' => 'ᾣ',\n  'ᾬ' => 'ᾤ',\n  'ᾭ' => 'ᾥ',\n  'ᾮ' => 'ᾦ',\n  'ᾯ' => 'ᾧ',\n  'Ᾰ' => 'ᾰ',\n  'Ᾱ' => 'ᾱ',\n  'Ὰ' => 'ὰ',\n  'Ά' => 'ά',\n  'ᾼ' => 'ᾳ',\n  'Ὲ' => 'ὲ',\n  'Έ' => 'έ',\n  'Ὴ' => 'ὴ',\n  'Ή' => 'ή',\n  'ῌ' => 'ῃ',\n  'Ῐ' => 'ῐ',\n  'Ῑ' => 'ῑ',\n  'Ὶ' => 'ὶ',\n  'Ί' => 'ί',\n  'Ῠ' => 'ῠ',\n  'Ῡ' => 'ῡ',\n  'Ὺ' => 'ὺ',\n  'Ύ' => 'ύ',\n  'Ῥ' => 'ῥ',\n  'Ὸ' => 'ὸ',\n  'Ό' => 'ό',\n  'Ὼ' => 'ὼ',\n  'Ώ' => 'ώ',\n  'ῼ' => 'ῳ',\n  'Ω' => 'ω',\n  'K' => 'k',\n  'Å' => 'å',\n  'Ⅎ' => 'ⅎ',\n  'Ⅰ' => 'ⅰ',\n  'Ⅱ' => 'ⅱ',\n  'Ⅲ' => 'ⅲ',\n  'Ⅳ' => 'ⅳ',\n  'Ⅴ' => 'ⅴ',\n  'Ⅵ' => 'ⅵ',\n  'Ⅶ' => 'ⅶ',\n  'Ⅷ' => 'ⅷ',\n  'Ⅸ' => 'ⅸ',\n  'Ⅹ' => 'ⅹ',\n  'Ⅺ' => 'ⅺ',\n  'Ⅻ' => 'ⅻ',\n  'Ⅼ' => 'ⅼ',\n  'Ⅽ' => 'ⅽ',\n  'Ⅾ' => 'ⅾ',\n  'Ⅿ' => 'ⅿ',\n  'Ↄ' => 'ↄ',\n  'Ⓐ' => 'ⓐ',\n  'Ⓑ' => 'ⓑ',\n  'Ⓒ' => 'ⓒ',\n  'Ⓓ' => 'ⓓ',\n  'Ⓔ' => 'ⓔ',\n  'Ⓕ' => 'ⓕ',\n  'Ⓖ' => 'ⓖ',\n  'Ⓗ' => 'ⓗ',\n  'Ⓘ' => 'ⓘ',\n  'Ⓙ' => 'ⓙ',\n  'Ⓚ' => 'ⓚ',\n  'Ⓛ' => 'ⓛ',\n  'Ⓜ' => 'ⓜ',\n  'Ⓝ' => 'ⓝ',\n  'Ⓞ' => 'ⓞ',\n  'Ⓟ' => 'ⓟ',\n  'Ⓠ' => 'ⓠ',\n  'Ⓡ' => 'ⓡ',\n  'Ⓢ' => 'ⓢ',\n  'Ⓣ' => 'ⓣ',\n  'Ⓤ' => 'ⓤ',\n  'Ⓥ' => 'ⓥ',\n  'Ⓦ' => 'ⓦ',\n  'Ⓧ' => 'ⓧ',\n  'Ⓨ' => 'ⓨ',\n  'Ⓩ' => 'ⓩ',\n  'Ⰰ' => 'ⰰ',\n  'Ⰱ' => 'ⰱ',\n  'Ⰲ' => 'ⰲ',\n  'Ⰳ' => 'ⰳ',\n  'Ⰴ' => 'ⰴ',\n  'Ⰵ' => 'ⰵ',\n  'Ⰶ' => 'ⰶ',\n  'Ⰷ' => 'ⰷ',\n  'Ⰸ' => 'ⰸ',\n  'Ⰹ' => 'ⰹ',\n  'Ⰺ' => 'ⰺ',\n  'Ⰻ' => 'ⰻ',\n  'Ⰼ' => 'ⰼ',\n  'Ⰽ' => 'ⰽ',\n  'Ⰾ' => 'ⰾ',\n  'Ⰿ' => 'ⰿ',\n  'Ⱀ' => 'ⱀ',\n  'Ⱁ' => 'ⱁ',\n  'Ⱂ' => 'ⱂ',\n  'Ⱃ' => 'ⱃ',\n  'Ⱄ' => 'ⱄ',\n  'Ⱅ' => 'ⱅ',\n  'Ⱆ' => 'ⱆ',\n  'Ⱇ' => 'ⱇ',\n  'Ⱈ' => 'ⱈ',\n  'Ⱉ' => 'ⱉ',\n  'Ⱊ' => 'ⱊ',\n  'Ⱋ' => 'ⱋ',\n  'Ⱌ' => 'ⱌ',\n  'Ⱍ' => 'ⱍ',\n  'Ⱎ' => 'ⱎ',\n  'Ⱏ' => 'ⱏ',\n  'Ⱐ' => 'ⱐ',\n  'Ⱑ' => 'ⱑ',\n  'Ⱒ' => 'ⱒ',\n  'Ⱓ' => 'ⱓ',\n  'Ⱔ' => 'ⱔ',\n  'Ⱕ' => 'ⱕ',\n  'Ⱖ' => 'ⱖ',\n  'Ⱗ' => 'ⱗ',\n  'Ⱘ' => 'ⱘ',\n  'Ⱙ' => 'ⱙ',\n  'Ⱚ' => 'ⱚ',\n  'Ⱛ' => 'ⱛ',\n  'Ⱜ' => 'ⱜ',\n  'Ⱝ' => 'ⱝ',\n  'Ⱞ' => 'ⱞ',\n  'Ⱡ' => 'ⱡ',\n  'Ɫ' => 'ɫ',\n  'Ᵽ' => 'ᵽ',\n  'Ɽ' => 'ɽ',\n  'Ⱨ' => 'ⱨ',\n  'Ⱪ' => 'ⱪ',\n  'Ⱬ' => 'ⱬ',\n  'Ɑ' => 'ɑ',\n  'Ɱ' => 'ɱ',\n  'Ɐ' => 'ɐ',\n  'Ɒ' => 'ɒ',\n  'Ⱳ' => 'ⱳ',\n  'Ⱶ' => 'ⱶ',\n  'Ȿ' => 'ȿ',\n  'Ɀ' => 'ɀ',\n  'Ⲁ' => 'ⲁ',\n  'Ⲃ' => 'ⲃ',\n  'Ⲅ' => 'ⲅ',\n  'Ⲇ' => 'ⲇ',\n  'Ⲉ' => 'ⲉ',\n  'Ⲋ' => 'ⲋ',\n  'Ⲍ' => 'ⲍ',\n  'Ⲏ' => 'ⲏ',\n  'Ⲑ' => 'ⲑ',\n  'Ⲓ' => 'ⲓ',\n  'Ⲕ' => 'ⲕ',\n  'Ⲗ' => 'ⲗ',\n  'Ⲙ' => 'ⲙ',\n  'Ⲛ' => 'ⲛ',\n  'Ⲝ' => 'ⲝ',\n  'Ⲟ' => 'ⲟ',\n  'Ⲡ' => 'ⲡ',\n  'Ⲣ' => 'ⲣ',\n  'Ⲥ' => 'ⲥ',\n  'Ⲧ' => 'ⲧ',\n  'Ⲩ' => 'ⲩ',\n  'Ⲫ' => 'ⲫ',\n  'Ⲭ' => 'ⲭ',\n  'Ⲯ' => 'ⲯ',\n  'Ⲱ' => 'ⲱ',\n  'Ⲳ' => 'ⲳ',\n  'Ⲵ' => 'ⲵ',\n  'Ⲷ' => 'ⲷ',\n  'Ⲹ' => 'ⲹ',\n  'Ⲻ' => 'ⲻ',\n  'Ⲽ' => 'ⲽ',\n  'Ⲿ' => 'ⲿ',\n  'Ⳁ' => 'ⳁ',\n  'Ⳃ' => 'ⳃ',\n  'Ⳅ' => 'ⳅ',\n  'Ⳇ' => 'ⳇ',\n  'Ⳉ' => 'ⳉ',\n  'Ⳋ' => 'ⳋ',\n  'Ⳍ' => 'ⳍ',\n  'Ⳏ' => 'ⳏ',\n  'Ⳑ' => 'ⳑ',\n  'Ⳓ' => 'ⳓ',\n  'Ⳕ' => 'ⳕ',\n  'Ⳗ' => 'ⳗ',\n  'Ⳙ' => 'ⳙ',\n  'Ⳛ' => 'ⳛ',\n  'Ⳝ' => 'ⳝ',\n  'Ⳟ' => 'ⳟ',\n  'Ⳡ' => 'ⳡ',\n  'Ⳣ' => 'ⳣ',\n  'Ⳬ' => 'ⳬ',\n  'Ⳮ' => 'ⳮ',\n  'Ⳳ' => 'ⳳ',\n  'Ꙁ' => 'ꙁ',\n  'Ꙃ' => 'ꙃ',\n  'Ꙅ' => 'ꙅ',\n  'Ꙇ' => 'ꙇ',\n  'Ꙉ' => 'ꙉ',\n  'Ꙋ' => 'ꙋ',\n  'Ꙍ' => 'ꙍ',\n  'Ꙏ' => 'ꙏ',\n  'Ꙑ' => 'ꙑ',\n  'Ꙓ' => 'ꙓ',\n  'Ꙕ' => 'ꙕ',\n  'Ꙗ' => 'ꙗ',\n  'Ꙙ' => 'ꙙ',\n  'Ꙛ' => 'ꙛ',\n  'Ꙝ' => 'ꙝ',\n  'Ꙟ' => 'ꙟ',\n  'Ꙡ' => 'ꙡ',\n  'Ꙣ' => 'ꙣ',\n  'Ꙥ' => 'ꙥ',\n  'Ꙧ' => 'ꙧ',\n  'Ꙩ' => 'ꙩ',\n  'Ꙫ' => 'ꙫ',\n  'Ꙭ' => 'ꙭ',\n  'Ꚁ' => 'ꚁ',\n  'Ꚃ' => 'ꚃ',\n  'Ꚅ' => 'ꚅ',\n  'Ꚇ' => 'ꚇ',\n  'Ꚉ' => 'ꚉ',\n  'Ꚋ' => 'ꚋ',\n  'Ꚍ' => 'ꚍ',\n  'Ꚏ' => 'ꚏ',\n  'Ꚑ' => 'ꚑ',\n  'Ꚓ' => 'ꚓ',\n  'Ꚕ' => 'ꚕ',\n  'Ꚗ' => 'ꚗ',\n  'Ꚙ' => 'ꚙ',\n  'Ꚛ' => 'ꚛ',\n  'Ꜣ' => 'ꜣ',\n  'Ꜥ' => 'ꜥ',\n  'Ꜧ' => 'ꜧ',\n  'Ꜩ' => 'ꜩ',\n  'Ꜫ' => 'ꜫ',\n  'Ꜭ' => 'ꜭ',\n  'Ꜯ' => 'ꜯ',\n  'Ꜳ' => 'ꜳ',\n  'Ꜵ' => 'ꜵ',\n  'Ꜷ' => 'ꜷ',\n  'Ꜹ' => 'ꜹ',\n  'Ꜻ' => 'ꜻ',\n  'Ꜽ' => 'ꜽ',\n  'Ꜿ' => 'ꜿ',\n  'Ꝁ' => 'ꝁ',\n  'Ꝃ' => 'ꝃ',\n  'Ꝅ' => 'ꝅ',\n  'Ꝇ' => 'ꝇ',\n  'Ꝉ' => 'ꝉ',\n  'Ꝋ' => 'ꝋ',\n  'Ꝍ' => 'ꝍ',\n  'Ꝏ' => 'ꝏ',\n  'Ꝑ' => 'ꝑ',\n  'Ꝓ' => 'ꝓ',\n  'Ꝕ' => 'ꝕ',\n  'Ꝗ' => 'ꝗ',\n  'Ꝙ' => 'ꝙ',\n  'Ꝛ' => 'ꝛ',\n  'Ꝝ' => 'ꝝ',\n  'Ꝟ' => 'ꝟ',\n  'Ꝡ' => 'ꝡ',\n  'Ꝣ' => 'ꝣ',\n  'Ꝥ' => 'ꝥ',\n  'Ꝧ' => 'ꝧ',\n  'Ꝩ' => 'ꝩ',\n  'Ꝫ' => 'ꝫ',\n  'Ꝭ' => 'ꝭ',\n  'Ꝯ' => 'ꝯ',\n  'Ꝺ' => 'ꝺ',\n  'Ꝼ' => 'ꝼ',\n  'Ᵹ' => 'ᵹ',\n  'Ꝿ' => 'ꝿ',\n  'Ꞁ' => 'ꞁ',\n  'Ꞃ' => 'ꞃ',\n  'Ꞅ' => 'ꞅ',\n  'Ꞇ' => 'ꞇ',\n  'Ꞌ' => 'ꞌ',\n  'Ɥ' => 'ɥ',\n  'Ꞑ' => 'ꞑ',\n  'Ꞓ' => 'ꞓ',\n  'Ꞗ' => 'ꞗ',\n  'Ꞙ' => 'ꞙ',\n  'Ꞛ' => 'ꞛ',\n  'Ꞝ' => 'ꞝ',\n  'Ꞟ' => 'ꞟ',\n  'Ꞡ' => 'ꞡ',\n  'Ꞣ' => 'ꞣ',\n  'Ꞥ' => 'ꞥ',\n  'Ꞧ' => 'ꞧ',\n  'Ꞩ' => 'ꞩ',\n  'Ɦ' => 'ɦ',\n  'Ɜ' => 'ɜ',\n  'Ɡ' => 'ɡ',\n  'Ɬ' => 'ɬ',\n  'Ɪ' => 'ɪ',\n  'Ʞ' => 'ʞ',\n  'Ʇ' => 'ʇ',\n  'Ʝ' => 'ʝ',\n  'Ꭓ' => 'ꭓ',\n  'Ꞵ' => 'ꞵ',\n  'Ꞷ' => 'ꞷ',\n  'Ꞹ' => 'ꞹ',\n  'Ꞻ' => 'ꞻ',\n  'Ꞽ' => 'ꞽ',\n  'Ꞿ' => 'ꞿ',\n  'Ꟃ' => 'ꟃ',\n  'Ꞔ' => 'ꞔ',\n  'Ʂ' => 'ʂ',\n  'Ᶎ' => 'ᶎ',\n  'Ꟈ' => 'ꟈ',\n  'Ꟊ' => 'ꟊ',\n  'Ꟶ' => 'ꟶ',\n  'Ａ' => 'ａ',\n  'Ｂ' => 'ｂ',\n  'Ｃ' => 'ｃ',\n  'Ｄ' => 'ｄ',\n  'Ｅ' => 'ｅ',\n  'Ｆ' => 'ｆ',\n  'Ｇ' => 'ｇ',\n  'Ｈ' => 'ｈ',\n  'Ｉ' => 'ｉ',\n  'Ｊ' => 'ｊ',\n  'Ｋ' => 'ｋ',\n  'Ｌ' => 'ｌ',\n  'Ｍ' => 'ｍ',\n  'Ｎ' => 'ｎ',\n  'Ｏ' => 'ｏ',\n  'Ｐ' => 'ｐ',\n  'Ｑ' => 'ｑ',\n  'Ｒ' => 'ｒ',\n  'Ｓ' => 'ｓ',\n  'Ｔ' => 'ｔ',\n  'Ｕ' => 'ｕ',\n  'Ｖ' => 'ｖ',\n  'Ｗ' => 'ｗ',\n  'Ｘ' => 'ｘ',\n  'Ｙ' => 'ｙ',\n  'Ｚ' => 'ｚ',\n  '𐐀' => '𐐨',\n  '𐐁' => '𐐩',\n  '𐐂' => '𐐪',\n  '𐐃' => '𐐫',\n  '𐐄' => '𐐬',\n  '𐐅' => '𐐭',\n  '𐐆' => '𐐮',\n  '𐐇' => '𐐯',\n  '𐐈' => '𐐰',\n  '𐐉' => '𐐱',\n  '𐐊' => '𐐲',\n  '𐐋' => '𐐳',\n  '𐐌' => '𐐴',\n  '𐐍' => '𐐵',\n  '𐐎' => '𐐶',\n  '𐐏' => '𐐷',\n  '𐐐' => '𐐸',\n  '𐐑' => '𐐹',\n  '𐐒' => '𐐺',\n  '𐐓' => '𐐻',\n  '𐐔' => '𐐼',\n  '𐐕' => '𐐽',\n  '𐐖' => '𐐾',\n  '𐐗' => '𐐿',\n  '𐐘' => '𐑀',\n  '𐐙' => '𐑁',\n  '𐐚' => '𐑂',\n  '𐐛' => '𐑃',\n  '𐐜' => '𐑄',\n  '𐐝' => '𐑅',\n  '𐐞' => '𐑆',\n  '𐐟' => '𐑇',\n  '𐐠' => '𐑈',\n  '𐐡' => '𐑉',\n  '𐐢' => '𐑊',\n  '𐐣' => '𐑋',\n  '𐐤' => '𐑌',\n  '𐐥' => '𐑍',\n  '𐐦' => '𐑎',\n  '𐐧' => '𐑏',\n  '𐒰' => '𐓘',\n  '𐒱' => '𐓙',\n  '𐒲' => '𐓚',\n  '𐒳' => '𐓛',\n  '𐒴' => '𐓜',\n  '𐒵' => '𐓝',\n  '𐒶' => '𐓞',\n  '𐒷' => '𐓟',\n  '𐒸' => '𐓠',\n  '𐒹' => '𐓡',\n  '𐒺' => '𐓢',\n  '𐒻' => '𐓣',\n  '𐒼' => '𐓤',\n  '𐒽' => '𐓥',\n  '𐒾' => '𐓦',\n  '𐒿' => '𐓧',\n  '𐓀' => '𐓨',\n  '𐓁' => '𐓩',\n  '𐓂' => '𐓪',\n  '𐓃' => '𐓫',\n  '𐓄' => '𐓬',\n  '𐓅' => '𐓭',\n  '𐓆' => '𐓮',\n  '𐓇' => '𐓯',\n  '𐓈' => '𐓰',\n  '𐓉' => '𐓱',\n  '𐓊' => '𐓲',\n  '𐓋' => '𐓳',\n  '𐓌' => '𐓴',\n  '𐓍' => '𐓵',\n  '𐓎' => '𐓶',\n  '𐓏' => '𐓷',\n  '𐓐' => '𐓸',\n  '𐓑' => '𐓹',\n  '𐓒' => '𐓺',\n  '𐓓' => '𐓻',\n  '𐲀' => '𐳀',\n  '𐲁' => '𐳁',\n  '𐲂' => '𐳂',\n  '𐲃' => '𐳃',\n  '𐲄' => '𐳄',\n  '𐲅' => '𐳅',\n  '𐲆' => '𐳆',\n  '𐲇' => '𐳇',\n  '𐲈' => '𐳈',\n  '𐲉' => '𐳉',\n  '𐲊' => '𐳊',\n  '𐲋' => '𐳋',\n  '𐲌' => '𐳌',\n  '𐲍' => '𐳍',\n  '𐲎' => '𐳎',\n  '𐲏' => '𐳏',\n  '𐲐' => '𐳐',\n  '𐲑' => '𐳑',\n  '𐲒' => '𐳒',\n  '𐲓' => '𐳓',\n  '𐲔' => '𐳔',\n  '𐲕' => '𐳕',\n  '𐲖' => '𐳖',\n  '𐲗' => '𐳗',\n  '𐲘' => '𐳘',\n  '𐲙' => '𐳙',\n  '𐲚' => '𐳚',\n  '𐲛' => '𐳛',\n  '𐲜' => '𐳜',\n  '𐲝' => '𐳝',\n  '𐲞' => '𐳞',\n  '𐲟' => '𐳟',\n  '𐲠' => '𐳠',\n  '𐲡' => '𐳡',\n  '𐲢' => '𐳢',\n  '𐲣' => '𐳣',\n  '𐲤' => '𐳤',\n  '𐲥' => '𐳥',\n  '𐲦' => '𐳦',\n  '𐲧' => '𐳧',\n  '𐲨' => '𐳨',\n  '𐲩' => '𐳩',\n  '𐲪' => '𐳪',\n  '𐲫' => '𐳫',\n  '𐲬' => '𐳬',\n  '𐲭' => '𐳭',\n  '𐲮' => '𐳮',\n  '𐲯' => '𐳯',\n  '𐲰' => '𐳰',\n  '𐲱' => '𐳱',\n  '𐲲' => '𐳲',\n  '𑢠' => '𑣀',\n  '𑢡' => '𑣁',\n  '𑢢' => '𑣂',\n  '𑢣' => '𑣃',\n  '𑢤' => '𑣄',\n  '𑢥' => '𑣅',\n  '𑢦' => '𑣆',\n  '𑢧' => '𑣇',\n  '𑢨' => '𑣈',\n  '𑢩' => '𑣉',\n  '𑢪' => '𑣊',\n  '𑢫' => '𑣋',\n  '𑢬' => '𑣌',\n  '𑢭' => '𑣍',\n  '𑢮' => '𑣎',\n  '𑢯' => '𑣏',\n  '𑢰' => '𑣐',\n  '𑢱' => '𑣑',\n  '𑢲' => '𑣒',\n  '𑢳' => '𑣓',\n  '𑢴' => '𑣔',\n  '𑢵' => '𑣕',\n  '𑢶' => '𑣖',\n  '𑢷' => '𑣗',\n  '𑢸' => '𑣘',\n  '𑢹' => '𑣙',\n  '𑢺' => '𑣚',\n  '𑢻' => '𑣛',\n  '𑢼' => '𑣜',\n  '𑢽' => '𑣝',\n  '𑢾' => '𑣞',\n  '𑢿' => '𑣟',\n  '𖹀' => '𖹠',\n  '𖹁' => '𖹡',\n  '𖹂' => '𖹢',\n  '𖹃' => '𖹣',\n  '𖹄' => '𖹤',\n  '𖹅' => '𖹥',\n  '𖹆' => '𖹦',\n  '𖹇' => '𖹧',\n  '𖹈' => '𖹨',\n  '𖹉' => '𖹩',\n  '𖹊' => '𖹪',\n  '𖹋' => '𖹫',\n  '𖹌' => '𖹬',\n  '𖹍' => '𖹭',\n  '𖹎' => '𖹮',\n  '𖹏' => '𖹯',\n  '𖹐' => '𖹰',\n  '𖹑' => '𖹱',\n  '𖹒' => '𖹲',\n  '𖹓' => '𖹳',\n  '𖹔' => '𖹴',\n  '𖹕' => '𖹵',\n  '𖹖' => '𖹶',\n  '𖹗' => '𖹷',\n  '𖹘' => '𖹸',\n  '𖹙' => '𖹹',\n  '𖹚' => '𖹺',\n  '𖹛' => '𖹻',\n  '𖹜' => '𖹼',\n  '𖹝' => '𖹽',\n  '𖹞' => '𖹾',\n  '𖹟' => '𖹿',\n  '𞤀' => '𞤢',\n  '𞤁' => '𞤣',\n  '𞤂' => '𞤤',\n  '𞤃' => '𞤥',\n  '𞤄' => '𞤦',\n  '𞤅' => '𞤧',\n  '𞤆' => '𞤨',\n  '𞤇' => '𞤩',\n  '𞤈' => '𞤪',\n  '𞤉' => '𞤫',\n  '𞤊' => '𞤬',\n  '𞤋' => '𞤭',\n  '𞤌' => '𞤮',\n  '𞤍' => '𞤯',\n  '𞤎' => '𞤰',\n  '𞤏' => '𞤱',\n  '𞤐' => '𞤲',\n  '𞤑' => '𞤳',\n  '𞤒' => '𞤴',\n  '𞤓' => '𞤵',\n  '𞤔' => '𞤶',\n  '𞤕' => '𞤷',\n  '𞤖' => '𞤸',\n  '𞤗' => '𞤹',\n  '𞤘' => '𞤺',\n  '𞤙' => '𞤻',\n  '𞤚' => '𞤼',\n  '𞤛' => '𞤽',\n  '𞤜' => '𞤾',\n  '𞤝' => '𞤿',\n  '𞤞' => '𞥀',\n  '𞤟' => '𞥁',\n  '𞤠' => '𞥂',\n  '𞤡' => '𞥃',\n);\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php",
    "content": "<?php\n\n// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt\n\nreturn '/(?<![\\x{0027}\\x{002E}\\x{003A}\\x{005E}\\x{0060}\\x{00A8}\\x{00AD}\\x{00AF}\\x{00B4}\\x{00B7}\\x{00B8}\\x{02B0}-\\x{02C1}\\x{02C2}-\\x{02C5}\\x{02C6}-\\x{02D1}\\x{02D2}-\\x{02DF}\\x{02E0}-\\x{02E4}\\x{02E5}-\\x{02EB}\\x{02EC}\\x{02ED}\\x{02EE}\\x{02EF}-\\x{02FF}\\x{0300}-\\x{036F}\\x{0374}\\x{0375}\\x{037A}\\x{0384}-\\x{0385}\\x{0387}\\x{0483}-\\x{0487}\\x{0488}-\\x{0489}\\x{0559}\\x{0591}-\\x{05BD}\\x{05BF}\\x{05C1}-\\x{05C2}\\x{05C4}-\\x{05C5}\\x{05C7}\\x{05F4}\\x{0600}-\\x{0605}\\x{0610}-\\x{061A}\\x{061C}\\x{0640}\\x{064B}-\\x{065F}\\x{0670}\\x{06D6}-\\x{06DC}\\x{06DD}\\x{06DF}-\\x{06E4}\\x{06E5}-\\x{06E6}\\x{06E7}-\\x{06E8}\\x{06EA}-\\x{06ED}\\x{070F}\\x{0711}\\x{0730}-\\x{074A}\\x{07A6}-\\x{07B0}\\x{07EB}-\\x{07F3}\\x{07F4}-\\x{07F5}\\x{07FA}\\x{07FD}\\x{0816}-\\x{0819}\\x{081A}\\x{081B}-\\x{0823}\\x{0824}\\x{0825}-\\x{0827}\\x{0828}\\x{0829}-\\x{082D}\\x{0859}-\\x{085B}\\x{08D3}-\\x{08E1}\\x{08E2}\\x{08E3}-\\x{0902}\\x{093A}\\x{093C}\\x{0941}-\\x{0948}\\x{094D}\\x{0951}-\\x{0957}\\x{0962}-\\x{0963}\\x{0971}\\x{0981}\\x{09BC}\\x{09C1}-\\x{09C4}\\x{09CD}\\x{09E2}-\\x{09E3}\\x{09FE}\\x{0A01}-\\x{0A02}\\x{0A3C}\\x{0A41}-\\x{0A42}\\x{0A47}-\\x{0A48}\\x{0A4B}-\\x{0A4D}\\x{0A51}\\x{0A70}-\\x{0A71}\\x{0A75}\\x{0A81}-\\x{0A82}\\x{0ABC}\\x{0AC1}-\\x{0AC5}\\x{0AC7}-\\x{0AC8}\\x{0ACD}\\x{0AE2}-\\x{0AE3}\\x{0AFA}-\\x{0AFF}\\x{0B01}\\x{0B3C}\\x{0B3F}\\x{0B41}-\\x{0B44}\\x{0B4D}\\x{0B56}\\x{0B62}-\\x{0B63}\\x{0B82}\\x{0BC0}\\x{0BCD}\\x{0C00}\\x{0C04}\\x{0C3E}-\\x{0C40}\\x{0C46}-\\x{0C48}\\x{0C4A}-\\x{0C4D}\\x{0C55}-\\x{0C56}\\x{0C62}-\\x{0C63}\\x{0C81}\\x{0CBC}\\x{0CBF}\\x{0CC6}\\x{0CCC}-\\x{0CCD}\\x{0CE2}-\\x{0CE3}\\x{0D00}-\\x{0D01}\\x{0D3B}-\\x{0D3C}\\x{0D41}-\\x{0D44}\\x{0D4D}\\x{0D62}-\\x{0D63}\\x{0DCA}\\x{0DD2}-\\x{0DD4}\\x{0DD6}\\x{0E31}\\x{0E34}-\\x{0E3A}\\x{0E46}\\x{0E47}-\\x{0E4E}\\x{0EB1}\\x{0EB4}-\\x{0EB9}\\x{0EBB}-\\x{0EBC}\\x{0EC6}\\x{0EC8}-\\x{0ECD}\\x{0F18}-\\x{0F19}\\x{0F35}\\x{0F37}\\x{0F39}\\x{0F71}-\\x{0F7E}\\x{0F80}-\\x{0F84}\\x{0F86}-\\x{0F87}\\x{0F8D}-\\x{0F97}\\x{0F99}-\\x{0FBC}\\x{0FC6}\\x{102D}-\\x{1030}\\x{1032}-\\x{1037}\\x{1039}-\\x{103A}\\x{103D}-\\x{103E}\\x{1058}-\\x{1059}\\x{105E}-\\x{1060}\\x{1071}-\\x{1074}\\x{1082}\\x{1085}-\\x{1086}\\x{108D}\\x{109D}\\x{10FC}\\x{135D}-\\x{135F}\\x{1712}-\\x{1714}\\x{1732}-\\x{1734}\\x{1752}-\\x{1753}\\x{1772}-\\x{1773}\\x{17B4}-\\x{17B5}\\x{17B7}-\\x{17BD}\\x{17C6}\\x{17C9}-\\x{17D3}\\x{17D7}\\x{17DD}\\x{180B}-\\x{180D}\\x{180E}\\x{1843}\\x{1885}-\\x{1886}\\x{18A9}\\x{1920}-\\x{1922}\\x{1927}-\\x{1928}\\x{1932}\\x{1939}-\\x{193B}\\x{1A17}-\\x{1A18}\\x{1A1B}\\x{1A56}\\x{1A58}-\\x{1A5E}\\x{1A60}\\x{1A62}\\x{1A65}-\\x{1A6C}\\x{1A73}-\\x{1A7C}\\x{1A7F}\\x{1AA7}\\x{1AB0}-\\x{1ABD}\\x{1ABE}\\x{1B00}-\\x{1B03}\\x{1B34}\\x{1B36}-\\x{1B3A}\\x{1B3C}\\x{1B42}\\x{1B6B}-\\x{1B73}\\x{1B80}-\\x{1B81}\\x{1BA2}-\\x{1BA5}\\x{1BA8}-\\x{1BA9}\\x{1BAB}-\\x{1BAD}\\x{1BE6}\\x{1BE8}-\\x{1BE9}\\x{1BED}\\x{1BEF}-\\x{1BF1}\\x{1C2C}-\\x{1C33}\\x{1C36}-\\x{1C37}\\x{1C78}-\\x{1C7D}\\x{1CD0}-\\x{1CD2}\\x{1CD4}-\\x{1CE0}\\x{1CE2}-\\x{1CE8}\\x{1CED}\\x{1CF4}\\x{1CF8}-\\x{1CF9}\\x{1D2C}-\\x{1D6A}\\x{1D78}\\x{1D9B}-\\x{1DBF}\\x{1DC0}-\\x{1DF9}\\x{1DFB}-\\x{1DFF}\\x{1FBD}\\x{1FBF}-\\x{1FC1}\\x{1FCD}-\\x{1FCF}\\x{1FDD}-\\x{1FDF}\\x{1FED}-\\x{1FEF}\\x{1FFD}-\\x{1FFE}\\x{200B}-\\x{200F}\\x{2018}\\x{2019}\\x{2024}\\x{2027}\\x{202A}-\\x{202E}\\x{2060}-\\x{2064}\\x{2066}-\\x{206F}\\x{2071}\\x{207F}\\x{2090}-\\x{209C}\\x{20D0}-\\x{20DC}\\x{20DD}-\\x{20E0}\\x{20E1}\\x{20E2}-\\x{20E4}\\x{20E5}-\\x{20F0}\\x{2C7C}-\\x{2C7D}\\x{2CEF}-\\x{2CF1}\\x{2D6F}\\x{2D7F}\\x{2DE0}-\\x{2DFF}\\x{2E2F}\\x{3005}\\x{302A}-\\x{302D}\\x{3031}-\\x{3035}\\x{303B}\\x{3099}-\\x{309A}\\x{309B}-\\x{309C}\\x{309D}-\\x{309E}\\x{30FC}-\\x{30FE}\\x{A015}\\x{A4F8}-\\x{A4FD}\\x{A60C}\\x{A66F}\\x{A670}-\\x{A672}\\x{A674}-\\x{A67D}\\x{A67F}\\x{A69C}-\\x{A69D}\\x{A69E}-\\x{A69F}\\x{A6F0}-\\x{A6F1}\\x{A700}-\\x{A716}\\x{A717}-\\x{A71F}\\x{A720}-\\x{A721}\\x{A770}\\x{A788}\\x{A789}-\\x{A78A}\\x{A7F8}-\\x{A7F9}\\x{A802}\\x{A806}\\x{A80B}\\x{A825}-\\x{A826}\\x{A8C4}-\\x{A8C5}\\x{A8E0}-\\x{A8F1}\\x{A8FF}\\x{A926}-\\x{A92D}\\x{A947}-\\x{A951}\\x{A980}-\\x{A982}\\x{A9B3}\\x{A9B6}-\\x{A9B9}\\x{A9BC}\\x{A9CF}\\x{A9E5}\\x{A9E6}\\x{AA29}-\\x{AA2E}\\x{AA31}-\\x{AA32}\\x{AA35}-\\x{AA36}\\x{AA43}\\x{AA4C}\\x{AA70}\\x{AA7C}\\x{AAB0}\\x{AAB2}-\\x{AAB4}\\x{AAB7}-\\x{AAB8}\\x{AABE}-\\x{AABF}\\x{AAC1}\\x{AADD}\\x{AAEC}-\\x{AAED}\\x{AAF3}-\\x{AAF4}\\x{AAF6}\\x{AB5B}\\x{AB5C}-\\x{AB5F}\\x{ABE5}\\x{ABE8}\\x{ABED}\\x{FB1E}\\x{FBB2}-\\x{FBC1}\\x{FE00}-\\x{FE0F}\\x{FE13}\\x{FE20}-\\x{FE2F}\\x{FE52}\\x{FE55}\\x{FEFF}\\x{FF07}\\x{FF0E}\\x{FF1A}\\x{FF3E}\\x{FF40}\\x{FF70}\\x{FF9E}-\\x{FF9F}\\x{FFE3}\\x{FFF9}-\\x{FFFB}\\x{101FD}\\x{102E0}\\x{10376}-\\x{1037A}\\x{10A01}-\\x{10A03}\\x{10A05}-\\x{10A06}\\x{10A0C}-\\x{10A0F}\\x{10A38}-\\x{10A3A}\\x{10A3F}\\x{10AE5}-\\x{10AE6}\\x{10D24}-\\x{10D27}\\x{10F46}-\\x{10F50}\\x{11001}\\x{11038}-\\x{11046}\\x{1107F}-\\x{11081}\\x{110B3}-\\x{110B6}\\x{110B9}-\\x{110BA}\\x{110BD}\\x{110CD}\\x{11100}-\\x{11102}\\x{11127}-\\x{1112B}\\x{1112D}-\\x{11134}\\x{11173}\\x{11180}-\\x{11181}\\x{111B6}-\\x{111BE}\\x{111C9}-\\x{111CC}\\x{1122F}-\\x{11231}\\x{11234}\\x{11236}-\\x{11237}\\x{1123E}\\x{112DF}\\x{112E3}-\\x{112EA}\\x{11300}-\\x{11301}\\x{1133B}-\\x{1133C}\\x{11340}\\x{11366}-\\x{1136C}\\x{11370}-\\x{11374}\\x{11438}-\\x{1143F}\\x{11442}-\\x{11444}\\x{11446}\\x{1145E}\\x{114B3}-\\x{114B8}\\x{114BA}\\x{114BF}-\\x{114C0}\\x{114C2}-\\x{114C3}\\x{115B2}-\\x{115B5}\\x{115BC}-\\x{115BD}\\x{115BF}-\\x{115C0}\\x{115DC}-\\x{115DD}\\x{11633}-\\x{1163A}\\x{1163D}\\x{1163F}-\\x{11640}\\x{116AB}\\x{116AD}\\x{116B0}-\\x{116B5}\\x{116B7}\\x{1171D}-\\x{1171F}\\x{11722}-\\x{11725}\\x{11727}-\\x{1172B}\\x{1182F}-\\x{11837}\\x{11839}-\\x{1183A}\\x{11A01}-\\x{11A0A}\\x{11A33}-\\x{11A38}\\x{11A3B}-\\x{11A3E}\\x{11A47}\\x{11A51}-\\x{11A56}\\x{11A59}-\\x{11A5B}\\x{11A8A}-\\x{11A96}\\x{11A98}-\\x{11A99}\\x{11C30}-\\x{11C36}\\x{11C38}-\\x{11C3D}\\x{11C3F}\\x{11C92}-\\x{11CA7}\\x{11CAA}-\\x{11CB0}\\x{11CB2}-\\x{11CB3}\\x{11CB5}-\\x{11CB6}\\x{11D31}-\\x{11D36}\\x{11D3A}\\x{11D3C}-\\x{11D3D}\\x{11D3F}-\\x{11D45}\\x{11D47}\\x{11D90}-\\x{11D91}\\x{11D95}\\x{11D97}\\x{11EF3}-\\x{11EF4}\\x{16AF0}-\\x{16AF4}\\x{16B30}-\\x{16B36}\\x{16B40}-\\x{16B43}\\x{16F8F}-\\x{16F92}\\x{16F93}-\\x{16F9F}\\x{16FE0}-\\x{16FE1}\\x{1BC9D}-\\x{1BC9E}\\x{1BCA0}-\\x{1BCA3}\\x{1D167}-\\x{1D169}\\x{1D173}-\\x{1D17A}\\x{1D17B}-\\x{1D182}\\x{1D185}-\\x{1D18B}\\x{1D1AA}-\\x{1D1AD}\\x{1D242}-\\x{1D244}\\x{1DA00}-\\x{1DA36}\\x{1DA3B}-\\x{1DA6C}\\x{1DA75}\\x{1DA84}\\x{1DA9B}-\\x{1DA9F}\\x{1DAA1}-\\x{1DAAF}\\x{1E000}-\\x{1E006}\\x{1E008}-\\x{1E018}\\x{1E01B}-\\x{1E021}\\x{1E023}-\\x{1E024}\\x{1E026}-\\x{1E02A}\\x{1E8D0}-\\x{1E8D6}\\x{1E944}-\\x{1E94A}\\x{1F3FB}-\\x{1F3FF}\\x{E0001}\\x{E0020}-\\x{E007F}\\x{E0100}-\\x{E01EF}])(\\pL)(\\pL*+)/u';\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php",
    "content": "<?php\n\nreturn array (\n  'a' => 'A',\n  'b' => 'B',\n  'c' => 'C',\n  'd' => 'D',\n  'e' => 'E',\n  'f' => 'F',\n  'g' => 'G',\n  'h' => 'H',\n  'i' => 'I',\n  'j' => 'J',\n  'k' => 'K',\n  'l' => 'L',\n  'm' => 'M',\n  'n' => 'N',\n  'o' => 'O',\n  'p' => 'P',\n  'q' => 'Q',\n  'r' => 'R',\n  's' => 'S',\n  't' => 'T',\n  'u' => 'U',\n  'v' => 'V',\n  'w' => 'W',\n  'x' => 'X',\n  'y' => 'Y',\n  'z' => 'Z',\n  'µ' => 'Μ',\n  'à' => 'À',\n  'á' => 'Á',\n  'â' => 'Â',\n  'ã' => 'Ã',\n  'ä' => 'Ä',\n  'å' => 'Å',\n  'æ' => 'Æ',\n  'ç' => 'Ç',\n  'è' => 'È',\n  'é' => 'É',\n  'ê' => 'Ê',\n  'ë' => 'Ë',\n  'ì' => 'Ì',\n  'í' => 'Í',\n  'î' => 'Î',\n  'ï' => 'Ï',\n  'ð' => 'Ð',\n  'ñ' => 'Ñ',\n  'ò' => 'Ò',\n  'ó' => 'Ó',\n  'ô' => 'Ô',\n  'õ' => 'Õ',\n  'ö' => 'Ö',\n  'ø' => 'Ø',\n  'ù' => 'Ù',\n  'ú' => 'Ú',\n  'û' => 'Û',\n  'ü' => 'Ü',\n  'ý' => 'Ý',\n  'þ' => 'Þ',\n  'ÿ' => 'Ÿ',\n  'ā' => 'Ā',\n  'ă' => 'Ă',\n  'ą' => 'Ą',\n  'ć' => 'Ć',\n  'ĉ' => 'Ĉ',\n  'ċ' => 'Ċ',\n  'č' => 'Č',\n  'ď' => 'Ď',\n  'đ' => 'Đ',\n  'ē' => 'Ē',\n  'ĕ' => 'Ĕ',\n  'ė' => 'Ė',\n  'ę' => 'Ę',\n  'ě' => 'Ě',\n  'ĝ' => 'Ĝ',\n  'ğ' => 'Ğ',\n  'ġ' => 'Ġ',\n  'ģ' => 'Ģ',\n  'ĥ' => 'Ĥ',\n  'ħ' => 'Ħ',\n  'ĩ' => 'Ĩ',\n  'ī' => 'Ī',\n  'ĭ' => 'Ĭ',\n  'į' => 'Į',\n  'ı' => 'I',\n  'ĳ' => 'Ĳ',\n  'ĵ' => 'Ĵ',\n  'ķ' => 'Ķ',\n  'ĺ' => 'Ĺ',\n  'ļ' => 'Ļ',\n  'ľ' => 'Ľ',\n  'ŀ' => 'Ŀ',\n  'ł' => 'Ł',\n  'ń' => 'Ń',\n  'ņ' => 'Ņ',\n  'ň' => 'Ň',\n  'ŋ' => 'Ŋ',\n  'ō' => 'Ō',\n  'ŏ' => 'Ŏ',\n  'ő' => 'Ő',\n  'œ' => 'Œ',\n  'ŕ' => 'Ŕ',\n  'ŗ' => 'Ŗ',\n  'ř' => 'Ř',\n  'ś' => 'Ś',\n  'ŝ' => 'Ŝ',\n  'ş' => 'Ş',\n  'š' => 'Š',\n  'ţ' => 'Ţ',\n  'ť' => 'Ť',\n  'ŧ' => 'Ŧ',\n  'ũ' => 'Ũ',\n  'ū' => 'Ū',\n  'ŭ' => 'Ŭ',\n  'ů' => 'Ů',\n  'ű' => 'Ű',\n  'ų' => 'Ų',\n  'ŵ' => 'Ŵ',\n  'ŷ' => 'Ŷ',\n  'ź' => 'Ź',\n  'ż' => 'Ż',\n  'ž' => 'Ž',\n  'ſ' => 'S',\n  'ƀ' => 'Ƀ',\n  'ƃ' => 'Ƃ',\n  'ƅ' => 'Ƅ',\n  'ƈ' => 'Ƈ',\n  'ƌ' => 'Ƌ',\n  'ƒ' => 'Ƒ',\n  'ƕ' => 'Ƕ',\n  'ƙ' => 'Ƙ',\n  'ƚ' => 'Ƚ',\n  'ƞ' => 'Ƞ',\n  'ơ' => 'Ơ',\n  'ƣ' => 'Ƣ',\n  'ƥ' => 'Ƥ',\n  'ƨ' => 'Ƨ',\n  'ƭ' => 'Ƭ',\n  'ư' => 'Ư',\n  'ƴ' => 'Ƴ',\n  'ƶ' => 'Ƶ',\n  'ƹ' => 'Ƹ',\n  'ƽ' => 'Ƽ',\n  'ƿ' => 'Ƿ',\n  'ǅ' => 'Ǆ',\n  'ǆ' => 'Ǆ',\n  'ǈ' => 'Ǉ',\n  'ǉ' => 'Ǉ',\n  'ǋ' => 'Ǌ',\n  'ǌ' => 'Ǌ',\n  'ǎ' => 'Ǎ',\n  'ǐ' => 'Ǐ',\n  'ǒ' => 'Ǒ',\n  'ǔ' => 'Ǔ',\n  'ǖ' => 'Ǖ',\n  'ǘ' => 'Ǘ',\n  'ǚ' => 'Ǚ',\n  'ǜ' => 'Ǜ',\n  'ǝ' => 'Ǝ',\n  'ǟ' => 'Ǟ',\n  'ǡ' => 'Ǡ',\n  'ǣ' => 'Ǣ',\n  'ǥ' => 'Ǥ',\n  'ǧ' => 'Ǧ',\n  'ǩ' => 'Ǩ',\n  'ǫ' => 'Ǫ',\n  'ǭ' => 'Ǭ',\n  'ǯ' => 'Ǯ',\n  'ǲ' => 'Ǳ',\n  'ǳ' => 'Ǳ',\n  'ǵ' => 'Ǵ',\n  'ǹ' => 'Ǹ',\n  'ǻ' => 'Ǻ',\n  'ǽ' => 'Ǽ',\n  'ǿ' => 'Ǿ',\n  'ȁ' => 'Ȁ',\n  'ȃ' => 'Ȃ',\n  'ȅ' => 'Ȅ',\n  'ȇ' => 'Ȇ',\n  'ȉ' => 'Ȉ',\n  'ȋ' => 'Ȋ',\n  'ȍ' => 'Ȍ',\n  'ȏ' => 'Ȏ',\n  'ȑ' => 'Ȑ',\n  'ȓ' => 'Ȓ',\n  'ȕ' => 'Ȕ',\n  'ȗ' => 'Ȗ',\n  'ș' => 'Ș',\n  'ț' => 'Ț',\n  'ȝ' => 'Ȝ',\n  'ȟ' => 'Ȟ',\n  'ȣ' => 'Ȣ',\n  'ȥ' => 'Ȥ',\n  'ȧ' => 'Ȧ',\n  'ȩ' => 'Ȩ',\n  'ȫ' => 'Ȫ',\n  'ȭ' => 'Ȭ',\n  'ȯ' => 'Ȯ',\n  'ȱ' => 'Ȱ',\n  'ȳ' => 'Ȳ',\n  'ȼ' => 'Ȼ',\n  'ȿ' => 'Ȿ',\n  'ɀ' => 'Ɀ',\n  'ɂ' => 'Ɂ',\n  'ɇ' => 'Ɇ',\n  'ɉ' => 'Ɉ',\n  'ɋ' => 'Ɋ',\n  'ɍ' => 'Ɍ',\n  'ɏ' => 'Ɏ',\n  'ɐ' => 'Ɐ',\n  'ɑ' => 'Ɑ',\n  'ɒ' => 'Ɒ',\n  'ɓ' => 'Ɓ',\n  'ɔ' => 'Ɔ',\n  'ɖ' => 'Ɖ',\n  'ɗ' => 'Ɗ',\n  'ə' => 'Ə',\n  'ɛ' => 'Ɛ',\n  'ɜ' => 'Ɜ',\n  'ɠ' => 'Ɠ',\n  'ɡ' => 'Ɡ',\n  'ɣ' => 'Ɣ',\n  'ɥ' => 'Ɥ',\n  'ɦ' => 'Ɦ',\n  'ɨ' => 'Ɨ',\n  'ɩ' => 'Ɩ',\n  'ɪ' => 'Ɪ',\n  'ɫ' => 'Ɫ',\n  'ɬ' => 'Ɬ',\n  'ɯ' => 'Ɯ',\n  'ɱ' => 'Ɱ',\n  'ɲ' => 'Ɲ',\n  'ɵ' => 'Ɵ',\n  'ɽ' => 'Ɽ',\n  'ʀ' => 'Ʀ',\n  'ʂ' => 'Ʂ',\n  'ʃ' => 'Ʃ',\n  'ʇ' => 'Ʇ',\n  'ʈ' => 'Ʈ',\n  'ʉ' => 'Ʉ',\n  'ʊ' => 'Ʊ',\n  'ʋ' => 'Ʋ',\n  'ʌ' => 'Ʌ',\n  'ʒ' => 'Ʒ',\n  'ʝ' => 'Ʝ',\n  'ʞ' => 'Ʞ',\n  'ͅ' => 'Ι',\n  'ͱ' => 'Ͱ',\n  'ͳ' => 'Ͳ',\n  'ͷ' => 'Ͷ',\n  'ͻ' => 'Ͻ',\n  'ͼ' => 'Ͼ',\n  'ͽ' => 'Ͽ',\n  'ά' => 'Ά',\n  'έ' => 'Έ',\n  'ή' => 'Ή',\n  'ί' => 'Ί',\n  'α' => 'Α',\n  'β' => 'Β',\n  'γ' => 'Γ',\n  'δ' => 'Δ',\n  'ε' => 'Ε',\n  'ζ' => 'Ζ',\n  'η' => 'Η',\n  'θ' => 'Θ',\n  'ι' => 'Ι',\n  'κ' => 'Κ',\n  'λ' => 'Λ',\n  'μ' => 'Μ',\n  'ν' => 'Ν',\n  'ξ' => 'Ξ',\n  'ο' => 'Ο',\n  'π' => 'Π',\n  'ρ' => 'Ρ',\n  'ς' => 'Σ',\n  'σ' => 'Σ',\n  'τ' => 'Τ',\n  'υ' => 'Υ',\n  'φ' => 'Φ',\n  'χ' => 'Χ',\n  'ψ' => 'Ψ',\n  'ω' => 'Ω',\n  'ϊ' => 'Ϊ',\n  'ϋ' => 'Ϋ',\n  'ό' => 'Ό',\n  'ύ' => 'Ύ',\n  'ώ' => 'Ώ',\n  'ϐ' => 'Β',\n  'ϑ' => 'Θ',\n  'ϕ' => 'Φ',\n  'ϖ' => 'Π',\n  'ϗ' => 'Ϗ',\n  'ϙ' => 'Ϙ',\n  'ϛ' => 'Ϛ',\n  'ϝ' => 'Ϝ',\n  'ϟ' => 'Ϟ',\n  'ϡ' => 'Ϡ',\n  'ϣ' => 'Ϣ',\n  'ϥ' => 'Ϥ',\n  'ϧ' => 'Ϧ',\n  'ϩ' => 'Ϩ',\n  'ϫ' => 'Ϫ',\n  'ϭ' => 'Ϭ',\n  'ϯ' => 'Ϯ',\n  'ϰ' => 'Κ',\n  'ϱ' => 'Ρ',\n  'ϲ' => 'Ϲ',\n  'ϳ' => 'Ϳ',\n  'ϵ' => 'Ε',\n  'ϸ' => 'Ϸ',\n  'ϻ' => 'Ϻ',\n  'а' => 'А',\n  'б' => 'Б',\n  'в' => 'В',\n  'г' => 'Г',\n  'д' => 'Д',\n  'е' => 'Е',\n  'ж' => 'Ж',\n  'з' => 'З',\n  'и' => 'И',\n  'й' => 'Й',\n  'к' => 'К',\n  'л' => 'Л',\n  'м' => 'М',\n  'н' => 'Н',\n  'о' => 'О',\n  'п' => 'П',\n  'р' => 'Р',\n  'с' => 'С',\n  'т' => 'Т',\n  'у' => 'У',\n  'ф' => 'Ф',\n  'х' => 'Х',\n  'ц' => 'Ц',\n  'ч' => 'Ч',\n  'ш' => 'Ш',\n  'щ' => 'Щ',\n  'ъ' => 'Ъ',\n  'ы' => 'Ы',\n  'ь' => 'Ь',\n  'э' => 'Э',\n  'ю' => 'Ю',\n  'я' => 'Я',\n  'ѐ' => 'Ѐ',\n  'ё' => 'Ё',\n  'ђ' => 'Ђ',\n  'ѓ' => 'Ѓ',\n  'є' => 'Є',\n  'ѕ' => 'Ѕ',\n  'і' => 'І',\n  'ї' => 'Ї',\n  'ј' => 'Ј',\n  'љ' => 'Љ',\n  'њ' => 'Њ',\n  'ћ' => 'Ћ',\n  'ќ' => 'Ќ',\n  'ѝ' => 'Ѝ',\n  'ў' => 'Ў',\n  'џ' => 'Џ',\n  'ѡ' => 'Ѡ',\n  'ѣ' => 'Ѣ',\n  'ѥ' => 'Ѥ',\n  'ѧ' => 'Ѧ',\n  'ѩ' => 'Ѩ',\n  'ѫ' => 'Ѫ',\n  'ѭ' => 'Ѭ',\n  'ѯ' => 'Ѯ',\n  'ѱ' => 'Ѱ',\n  'ѳ' => 'Ѳ',\n  'ѵ' => 'Ѵ',\n  'ѷ' => 'Ѷ',\n  'ѹ' => 'Ѹ',\n  'ѻ' => 'Ѻ',\n  'ѽ' => 'Ѽ',\n  'ѿ' => 'Ѿ',\n  'ҁ' => 'Ҁ',\n  'ҋ' => 'Ҋ',\n  'ҍ' => 'Ҍ',\n  'ҏ' => 'Ҏ',\n  'ґ' => 'Ґ',\n  'ғ' => 'Ғ',\n  'ҕ' => 'Ҕ',\n  'җ' => 'Җ',\n  'ҙ' => 'Ҙ',\n  'қ' => 'Қ',\n  'ҝ' => 'Ҝ',\n  'ҟ' => 'Ҟ',\n  'ҡ' => 'Ҡ',\n  'ң' => 'Ң',\n  'ҥ' => 'Ҥ',\n  'ҧ' => 'Ҧ',\n  'ҩ' => 'Ҩ',\n  'ҫ' => 'Ҫ',\n  'ҭ' => 'Ҭ',\n  'ү' => 'Ү',\n  'ұ' => 'Ұ',\n  'ҳ' => 'Ҳ',\n  'ҵ' => 'Ҵ',\n  'ҷ' => 'Ҷ',\n  'ҹ' => 'Ҹ',\n  'һ' => 'Һ',\n  'ҽ' => 'Ҽ',\n  'ҿ' => 'Ҿ',\n  'ӂ' => 'Ӂ',\n  'ӄ' => 'Ӄ',\n  'ӆ' => 'Ӆ',\n  'ӈ' => 'Ӈ',\n  'ӊ' => 'Ӊ',\n  'ӌ' => 'Ӌ',\n  'ӎ' => 'Ӎ',\n  'ӏ' => 'Ӏ',\n  'ӑ' => 'Ӑ',\n  'ӓ' => 'Ӓ',\n  'ӕ' => 'Ӕ',\n  'ӗ' => 'Ӗ',\n  'ә' => 'Ә',\n  'ӛ' => 'Ӛ',\n  'ӝ' => 'Ӝ',\n  'ӟ' => 'Ӟ',\n  'ӡ' => 'Ӡ',\n  'ӣ' => 'Ӣ',\n  'ӥ' => 'Ӥ',\n  'ӧ' => 'Ӧ',\n  'ө' => 'Ө',\n  'ӫ' => 'Ӫ',\n  'ӭ' => 'Ӭ',\n  'ӯ' => 'Ӯ',\n  'ӱ' => 'Ӱ',\n  'ӳ' => 'Ӳ',\n  'ӵ' => 'Ӵ',\n  'ӷ' => 'Ӷ',\n  'ӹ' => 'Ӹ',\n  'ӻ' => 'Ӻ',\n  'ӽ' => 'Ӽ',\n  'ӿ' => 'Ӿ',\n  'ԁ' => 'Ԁ',\n  'ԃ' => 'Ԃ',\n  'ԅ' => 'Ԅ',\n  'ԇ' => 'Ԇ',\n  'ԉ' => 'Ԉ',\n  'ԋ' => 'Ԋ',\n  'ԍ' => 'Ԍ',\n  'ԏ' => 'Ԏ',\n  'ԑ' => 'Ԑ',\n  'ԓ' => 'Ԓ',\n  'ԕ' => 'Ԕ',\n  'ԗ' => 'Ԗ',\n  'ԙ' => 'Ԙ',\n  'ԛ' => 'Ԛ',\n  'ԝ' => 'Ԝ',\n  'ԟ' => 'Ԟ',\n  'ԡ' => 'Ԡ',\n  'ԣ' => 'Ԣ',\n  'ԥ' => 'Ԥ',\n  'ԧ' => 'Ԧ',\n  'ԩ' => 'Ԩ',\n  'ԫ' => 'Ԫ',\n  'ԭ' => 'Ԭ',\n  'ԯ' => 'Ԯ',\n  'ա' => 'Ա',\n  'բ' => 'Բ',\n  'գ' => 'Գ',\n  'դ' => 'Դ',\n  'ե' => 'Ե',\n  'զ' => 'Զ',\n  'է' => 'Է',\n  'ը' => 'Ը',\n  'թ' => 'Թ',\n  'ժ' => 'Ժ',\n  'ի' => 'Ի',\n  'լ' => 'Լ',\n  'խ' => 'Խ',\n  'ծ' => 'Ծ',\n  'կ' => 'Կ',\n  'հ' => 'Հ',\n  'ձ' => 'Ձ',\n  'ղ' => 'Ղ',\n  'ճ' => 'Ճ',\n  'մ' => 'Մ',\n  'յ' => 'Յ',\n  'ն' => 'Ն',\n  'շ' => 'Շ',\n  'ո' => 'Ո',\n  'չ' => 'Չ',\n  'պ' => 'Պ',\n  'ջ' => 'Ջ',\n  'ռ' => 'Ռ',\n  'ս' => 'Ս',\n  'վ' => 'Վ',\n  'տ' => 'Տ',\n  'ր' => 'Ր',\n  'ց' => 'Ց',\n  'ւ' => 'Ւ',\n  'փ' => 'Փ',\n  'ք' => 'Ք',\n  'օ' => 'Օ',\n  'ֆ' => 'Ֆ',\n  'ა' => 'Ა',\n  'ბ' => 'Ბ',\n  'გ' => 'Გ',\n  'დ' => 'Დ',\n  'ე' => 'Ე',\n  'ვ' => 'Ვ',\n  'ზ' => 'Ზ',\n  'თ' => 'Თ',\n  'ი' => 'Ი',\n  'კ' => 'Კ',\n  'ლ' => 'Ლ',\n  'მ' => 'Მ',\n  'ნ' => 'Ნ',\n  'ო' => 'Ო',\n  'პ' => 'Პ',\n  'ჟ' => 'Ჟ',\n  'რ' => 'Რ',\n  'ს' => 'Ს',\n  'ტ' => 'Ტ',\n  'უ' => 'Უ',\n  'ფ' => 'Ფ',\n  'ქ' => 'Ქ',\n  'ღ' => 'Ღ',\n  'ყ' => 'Ყ',\n  'შ' => 'Შ',\n  'ჩ' => 'Ჩ',\n  'ც' => 'Ც',\n  'ძ' => 'Ძ',\n  'წ' => 'Წ',\n  'ჭ' => 'Ჭ',\n  'ხ' => 'Ხ',\n  'ჯ' => 'Ჯ',\n  'ჰ' => 'Ჰ',\n  'ჱ' => 'Ჱ',\n  'ჲ' => 'Ჲ',\n  'ჳ' => 'Ჳ',\n  'ჴ' => 'Ჴ',\n  'ჵ' => 'Ჵ',\n  'ჶ' => 'Ჶ',\n  'ჷ' => 'Ჷ',\n  'ჸ' => 'Ჸ',\n  'ჹ' => 'Ჹ',\n  'ჺ' => 'Ჺ',\n  'ჽ' => 'Ჽ',\n  'ჾ' => 'Ჾ',\n  'ჿ' => 'Ჿ',\n  'ᏸ' => 'Ᏸ',\n  'ᏹ' => 'Ᏹ',\n  'ᏺ' => 'Ᏺ',\n  'ᏻ' => 'Ᏻ',\n  'ᏼ' => 'Ᏼ',\n  'ᏽ' => 'Ᏽ',\n  'ᲀ' => 'В',\n  'ᲁ' => 'Д',\n  'ᲂ' => 'О',\n  'ᲃ' => 'С',\n  'ᲄ' => 'Т',\n  'ᲅ' => 'Т',\n  'ᲆ' => 'Ъ',\n  'ᲇ' => 'Ѣ',\n  'ᲈ' => 'Ꙋ',\n  'ᵹ' => 'Ᵹ',\n  'ᵽ' => 'Ᵽ',\n  'ᶎ' => 'Ᶎ',\n  'ḁ' => 'Ḁ',\n  'ḃ' => 'Ḃ',\n  'ḅ' => 'Ḅ',\n  'ḇ' => 'Ḇ',\n  'ḉ' => 'Ḉ',\n  'ḋ' => 'Ḋ',\n  'ḍ' => 'Ḍ',\n  'ḏ' => 'Ḏ',\n  'ḑ' => 'Ḑ',\n  'ḓ' => 'Ḓ',\n  'ḕ' => 'Ḕ',\n  'ḗ' => 'Ḗ',\n  'ḙ' => 'Ḙ',\n  'ḛ' => 'Ḛ',\n  'ḝ' => 'Ḝ',\n  'ḟ' => 'Ḟ',\n  'ḡ' => 'Ḡ',\n  'ḣ' => 'Ḣ',\n  'ḥ' => 'Ḥ',\n  'ḧ' => 'Ḧ',\n  'ḩ' => 'Ḩ',\n  'ḫ' => 'Ḫ',\n  'ḭ' => 'Ḭ',\n  'ḯ' => 'Ḯ',\n  'ḱ' => 'Ḱ',\n  'ḳ' => 'Ḳ',\n  'ḵ' => 'Ḵ',\n  'ḷ' => 'Ḷ',\n  'ḹ' => 'Ḹ',\n  'ḻ' => 'Ḻ',\n  'ḽ' => 'Ḽ',\n  'ḿ' => 'Ḿ',\n  'ṁ' => 'Ṁ',\n  'ṃ' => 'Ṃ',\n  'ṅ' => 'Ṅ',\n  'ṇ' => 'Ṇ',\n  'ṉ' => 'Ṉ',\n  'ṋ' => 'Ṋ',\n  'ṍ' => 'Ṍ',\n  'ṏ' => 'Ṏ',\n  'ṑ' => 'Ṑ',\n  'ṓ' => 'Ṓ',\n  'ṕ' => 'Ṕ',\n  'ṗ' => 'Ṗ',\n  'ṙ' => 'Ṙ',\n  'ṛ' => 'Ṛ',\n  'ṝ' => 'Ṝ',\n  'ṟ' => 'Ṟ',\n  'ṡ' => 'Ṡ',\n  'ṣ' => 'Ṣ',\n  'ṥ' => 'Ṥ',\n  'ṧ' => 'Ṧ',\n  'ṩ' => 'Ṩ',\n  'ṫ' => 'Ṫ',\n  'ṭ' => 'Ṭ',\n  'ṯ' => 'Ṯ',\n  'ṱ' => 'Ṱ',\n  'ṳ' => 'Ṳ',\n  'ṵ' => 'Ṵ',\n  'ṷ' => 'Ṷ',\n  'ṹ' => 'Ṹ',\n  'ṻ' => 'Ṻ',\n  'ṽ' => 'Ṽ',\n  'ṿ' => 'Ṿ',\n  'ẁ' => 'Ẁ',\n  'ẃ' => 'Ẃ',\n  'ẅ' => 'Ẅ',\n  'ẇ' => 'Ẇ',\n  'ẉ' => 'Ẉ',\n  'ẋ' => 'Ẋ',\n  'ẍ' => 'Ẍ',\n  'ẏ' => 'Ẏ',\n  'ẑ' => 'Ẑ',\n  'ẓ' => 'Ẓ',\n  'ẕ' => 'Ẕ',\n  'ẛ' => 'Ṡ',\n  'ạ' => 'Ạ',\n  'ả' => 'Ả',\n  'ấ' => 'Ấ',\n  'ầ' => 'Ầ',\n  'ẩ' => 'Ẩ',\n  'ẫ' => 'Ẫ',\n  'ậ' => 'Ậ',\n  'ắ' => 'Ắ',\n  'ằ' => 'Ằ',\n  'ẳ' => 'Ẳ',\n  'ẵ' => 'Ẵ',\n  'ặ' => 'Ặ',\n  'ẹ' => 'Ẹ',\n  'ẻ' => 'Ẻ',\n  'ẽ' => 'Ẽ',\n  'ế' => 'Ế',\n  'ề' => 'Ề',\n  'ể' => 'Ể',\n  'ễ' => 'Ễ',\n  'ệ' => 'Ệ',\n  'ỉ' => 'Ỉ',\n  'ị' => 'Ị',\n  'ọ' => 'Ọ',\n  'ỏ' => 'Ỏ',\n  'ố' => 'Ố',\n  'ồ' => 'Ồ',\n  'ổ' => 'Ổ',\n  'ỗ' => 'Ỗ',\n  'ộ' => 'Ộ',\n  'ớ' => 'Ớ',\n  'ờ' => 'Ờ',\n  'ở' => 'Ở',\n  'ỡ' => 'Ỡ',\n  'ợ' => 'Ợ',\n  'ụ' => 'Ụ',\n  'ủ' => 'Ủ',\n  'ứ' => 'Ứ',\n  'ừ' => 'Ừ',\n  'ử' => 'Ử',\n  'ữ' => 'Ữ',\n  'ự' => 'Ự',\n  'ỳ' => 'Ỳ',\n  'ỵ' => 'Ỵ',\n  'ỷ' => 'Ỷ',\n  'ỹ' => 'Ỹ',\n  'ỻ' => 'Ỻ',\n  'ỽ' => 'Ỽ',\n  'ỿ' => 'Ỿ',\n  'ἀ' => 'Ἀ',\n  'ἁ' => 'Ἁ',\n  'ἂ' => 'Ἂ',\n  'ἃ' => 'Ἃ',\n  'ἄ' => 'Ἄ',\n  'ἅ' => 'Ἅ',\n  'ἆ' => 'Ἆ',\n  'ἇ' => 'Ἇ',\n  'ἐ' => 'Ἐ',\n  'ἑ' => 'Ἑ',\n  'ἒ' => 'Ἒ',\n  'ἓ' => 'Ἓ',\n  'ἔ' => 'Ἔ',\n  'ἕ' => 'Ἕ',\n  'ἠ' => 'Ἠ',\n  'ἡ' => 'Ἡ',\n  'ἢ' => 'Ἢ',\n  'ἣ' => 'Ἣ',\n  'ἤ' => 'Ἤ',\n  'ἥ' => 'Ἥ',\n  'ἦ' => 'Ἦ',\n  'ἧ' => 'Ἧ',\n  'ἰ' => 'Ἰ',\n  'ἱ' => 'Ἱ',\n  'ἲ' => 'Ἲ',\n  'ἳ' => 'Ἳ',\n  'ἴ' => 'Ἴ',\n  'ἵ' => 'Ἵ',\n  'ἶ' => 'Ἶ',\n  'ἷ' => 'Ἷ',\n  'ὀ' => 'Ὀ',\n  'ὁ' => 'Ὁ',\n  'ὂ' => 'Ὂ',\n  'ὃ' => 'Ὃ',\n  'ὄ' => 'Ὄ',\n  'ὅ' => 'Ὅ',\n  'ὑ' => 'Ὑ',\n  'ὓ' => 'Ὓ',\n  'ὕ' => 'Ὕ',\n  'ὗ' => 'Ὗ',\n  'ὠ' => 'Ὠ',\n  'ὡ' => 'Ὡ',\n  'ὢ' => 'Ὢ',\n  'ὣ' => 'Ὣ',\n  'ὤ' => 'Ὤ',\n  'ὥ' => 'Ὥ',\n  'ὦ' => 'Ὦ',\n  'ὧ' => 'Ὧ',\n  'ὰ' => 'Ὰ',\n  'ά' => 'Ά',\n  'ὲ' => 'Ὲ',\n  'έ' => 'Έ',\n  'ὴ' => 'Ὴ',\n  'ή' => 'Ή',\n  'ὶ' => 'Ὶ',\n  'ί' => 'Ί',\n  'ὸ' => 'Ὸ',\n  'ό' => 'Ό',\n  'ὺ' => 'Ὺ',\n  'ύ' => 'Ύ',\n  'ὼ' => 'Ὼ',\n  'ώ' => 'Ώ',\n  'ᾀ' => 'ἈΙ',\n  'ᾁ' => 'ἉΙ',\n  'ᾂ' => 'ἊΙ',\n  'ᾃ' => 'ἋΙ',\n  'ᾄ' => 'ἌΙ',\n  'ᾅ' => 'ἍΙ',\n  'ᾆ' => 'ἎΙ',\n  'ᾇ' => 'ἏΙ',\n  'ᾐ' => 'ἨΙ',\n  'ᾑ' => 'ἩΙ',\n  'ᾒ' => 'ἪΙ',\n  'ᾓ' => 'ἫΙ',\n  'ᾔ' => 'ἬΙ',\n  'ᾕ' => 'ἭΙ',\n  'ᾖ' => 'ἮΙ',\n  'ᾗ' => 'ἯΙ',\n  'ᾠ' => 'ὨΙ',\n  'ᾡ' => 'ὩΙ',\n  'ᾢ' => 'ὪΙ',\n  'ᾣ' => 'ὫΙ',\n  'ᾤ' => 'ὬΙ',\n  'ᾥ' => 'ὭΙ',\n  'ᾦ' => 'ὮΙ',\n  'ᾧ' => 'ὯΙ',\n  'ᾰ' => 'Ᾰ',\n  'ᾱ' => 'Ᾱ',\n  'ᾳ' => 'ΑΙ',\n  'ι' => 'Ι',\n  'ῃ' => 'ΗΙ',\n  'ῐ' => 'Ῐ',\n  'ῑ' => 'Ῑ',\n  'ῠ' => 'Ῠ',\n  'ῡ' => 'Ῡ',\n  'ῥ' => 'Ῥ',\n  'ῳ' => 'ΩΙ',\n  'ⅎ' => 'Ⅎ',\n  'ⅰ' => 'Ⅰ',\n  'ⅱ' => 'Ⅱ',\n  'ⅲ' => 'Ⅲ',\n  'ⅳ' => 'Ⅳ',\n  'ⅴ' => 'Ⅴ',\n  'ⅵ' => 'Ⅵ',\n  'ⅶ' => 'Ⅶ',\n  'ⅷ' => 'Ⅷ',\n  'ⅸ' => 'Ⅸ',\n  'ⅹ' => 'Ⅹ',\n  'ⅺ' => 'Ⅺ',\n  'ⅻ' => 'Ⅻ',\n  'ⅼ' => 'Ⅼ',\n  'ⅽ' => 'Ⅽ',\n  'ⅾ' => 'Ⅾ',\n  'ⅿ' => 'Ⅿ',\n  'ↄ' => 'Ↄ',\n  'ⓐ' => 'Ⓐ',\n  'ⓑ' => 'Ⓑ',\n  'ⓒ' => 'Ⓒ',\n  'ⓓ' => 'Ⓓ',\n  'ⓔ' => 'Ⓔ',\n  'ⓕ' => 'Ⓕ',\n  'ⓖ' => 'Ⓖ',\n  'ⓗ' => 'Ⓗ',\n  'ⓘ' => 'Ⓘ',\n  'ⓙ' => 'Ⓙ',\n  'ⓚ' => 'Ⓚ',\n  'ⓛ' => 'Ⓛ',\n  'ⓜ' => 'Ⓜ',\n  'ⓝ' => 'Ⓝ',\n  'ⓞ' => 'Ⓞ',\n  'ⓟ' => 'Ⓟ',\n  'ⓠ' => 'Ⓠ',\n  'ⓡ' => 'Ⓡ',\n  'ⓢ' => 'Ⓢ',\n  'ⓣ' => 'Ⓣ',\n  'ⓤ' => 'Ⓤ',\n  'ⓥ' => 'Ⓥ',\n  'ⓦ' => 'Ⓦ',\n  'ⓧ' => 'Ⓧ',\n  'ⓨ' => 'Ⓨ',\n  'ⓩ' => 'Ⓩ',\n  'ⰰ' => 'Ⰰ',\n  'ⰱ' => 'Ⰱ',\n  'ⰲ' => 'Ⰲ',\n  'ⰳ' => 'Ⰳ',\n  'ⰴ' => 'Ⰴ',\n  'ⰵ' => 'Ⰵ',\n  'ⰶ' => 'Ⰶ',\n  'ⰷ' => 'Ⰷ',\n  'ⰸ' => 'Ⰸ',\n  'ⰹ' => 'Ⰹ',\n  'ⰺ' => 'Ⰺ',\n  'ⰻ' => 'Ⰻ',\n  'ⰼ' => 'Ⰼ',\n  'ⰽ' => 'Ⰽ',\n  'ⰾ' => 'Ⰾ',\n  'ⰿ' => 'Ⰿ',\n  'ⱀ' => 'Ⱀ',\n  'ⱁ' => 'Ⱁ',\n  'ⱂ' => 'Ⱂ',\n  'ⱃ' => 'Ⱃ',\n  'ⱄ' => 'Ⱄ',\n  'ⱅ' => 'Ⱅ',\n  'ⱆ' => 'Ⱆ',\n  'ⱇ' => 'Ⱇ',\n  'ⱈ' => 'Ⱈ',\n  'ⱉ' => 'Ⱉ',\n  'ⱊ' => 'Ⱊ',\n  'ⱋ' => 'Ⱋ',\n  'ⱌ' => 'Ⱌ',\n  'ⱍ' => 'Ⱍ',\n  'ⱎ' => 'Ⱎ',\n  'ⱏ' => 'Ⱏ',\n  'ⱐ' => 'Ⱐ',\n  'ⱑ' => 'Ⱑ',\n  'ⱒ' => 'Ⱒ',\n  'ⱓ' => 'Ⱓ',\n  'ⱔ' => 'Ⱔ',\n  'ⱕ' => 'Ⱕ',\n  'ⱖ' => 'Ⱖ',\n  'ⱗ' => 'Ⱗ',\n  'ⱘ' => 'Ⱘ',\n  'ⱙ' => 'Ⱙ',\n  'ⱚ' => 'Ⱚ',\n  'ⱛ' => 'Ⱛ',\n  'ⱜ' => 'Ⱜ',\n  'ⱝ' => 'Ⱝ',\n  'ⱞ' => 'Ⱞ',\n  'ⱡ' => 'Ⱡ',\n  'ⱥ' => 'Ⱥ',\n  'ⱦ' => 'Ⱦ',\n  'ⱨ' => 'Ⱨ',\n  'ⱪ' => 'Ⱪ',\n  'ⱬ' => 'Ⱬ',\n  'ⱳ' => 'Ⱳ',\n  'ⱶ' => 'Ⱶ',\n  'ⲁ' => 'Ⲁ',\n  'ⲃ' => 'Ⲃ',\n  'ⲅ' => 'Ⲅ',\n  'ⲇ' => 'Ⲇ',\n  'ⲉ' => 'Ⲉ',\n  'ⲋ' => 'Ⲋ',\n  'ⲍ' => 'Ⲍ',\n  'ⲏ' => 'Ⲏ',\n  'ⲑ' => 'Ⲑ',\n  'ⲓ' => 'Ⲓ',\n  'ⲕ' => 'Ⲕ',\n  'ⲗ' => 'Ⲗ',\n  'ⲙ' => 'Ⲙ',\n  'ⲛ' => 'Ⲛ',\n  'ⲝ' => 'Ⲝ',\n  'ⲟ' => 'Ⲟ',\n  'ⲡ' => 'Ⲡ',\n  'ⲣ' => 'Ⲣ',\n  'ⲥ' => 'Ⲥ',\n  'ⲧ' => 'Ⲧ',\n  'ⲩ' => 'Ⲩ',\n  'ⲫ' => 'Ⲫ',\n  'ⲭ' => 'Ⲭ',\n  'ⲯ' => 'Ⲯ',\n  'ⲱ' => 'Ⲱ',\n  'ⲳ' => 'Ⲳ',\n  'ⲵ' => 'Ⲵ',\n  'ⲷ' => 'Ⲷ',\n  'ⲹ' => 'Ⲹ',\n  'ⲻ' => 'Ⲻ',\n  'ⲽ' => 'Ⲽ',\n  'ⲿ' => 'Ⲿ',\n  'ⳁ' => 'Ⳁ',\n  'ⳃ' => 'Ⳃ',\n  'ⳅ' => 'Ⳅ',\n  'ⳇ' => 'Ⳇ',\n  'ⳉ' => 'Ⳉ',\n  'ⳋ' => 'Ⳋ',\n  'ⳍ' => 'Ⳍ',\n  'ⳏ' => 'Ⳏ',\n  'ⳑ' => 'Ⳑ',\n  'ⳓ' => 'Ⳓ',\n  'ⳕ' => 'Ⳕ',\n  'ⳗ' => 'Ⳗ',\n  'ⳙ' => 'Ⳙ',\n  'ⳛ' => 'Ⳛ',\n  'ⳝ' => 'Ⳝ',\n  'ⳟ' => 'Ⳟ',\n  'ⳡ' => 'Ⳡ',\n  'ⳣ' => 'Ⳣ',\n  'ⳬ' => 'Ⳬ',\n  'ⳮ' => 'Ⳮ',\n  'ⳳ' => 'Ⳳ',\n  'ⴀ' => 'Ⴀ',\n  'ⴁ' => 'Ⴁ',\n  'ⴂ' => 'Ⴂ',\n  'ⴃ' => 'Ⴃ',\n  'ⴄ' => 'Ⴄ',\n  'ⴅ' => 'Ⴅ',\n  'ⴆ' => 'Ⴆ',\n  'ⴇ' => 'Ⴇ',\n  'ⴈ' => 'Ⴈ',\n  'ⴉ' => 'Ⴉ',\n  'ⴊ' => 'Ⴊ',\n  'ⴋ' => 'Ⴋ',\n  'ⴌ' => 'Ⴌ',\n  'ⴍ' => 'Ⴍ',\n  'ⴎ' => 'Ⴎ',\n  'ⴏ' => 'Ⴏ',\n  'ⴐ' => 'Ⴐ',\n  'ⴑ' => 'Ⴑ',\n  'ⴒ' => 'Ⴒ',\n  'ⴓ' => 'Ⴓ',\n  'ⴔ' => 'Ⴔ',\n  'ⴕ' => 'Ⴕ',\n  'ⴖ' => 'Ⴖ',\n  'ⴗ' => 'Ⴗ',\n  'ⴘ' => 'Ⴘ',\n  'ⴙ' => 'Ⴙ',\n  'ⴚ' => 'Ⴚ',\n  'ⴛ' => 'Ⴛ',\n  'ⴜ' => 'Ⴜ',\n  'ⴝ' => 'Ⴝ',\n  'ⴞ' => 'Ⴞ',\n  'ⴟ' => 'Ⴟ',\n  'ⴠ' => 'Ⴠ',\n  'ⴡ' => 'Ⴡ',\n  'ⴢ' => 'Ⴢ',\n  'ⴣ' => 'Ⴣ',\n  'ⴤ' => 'Ⴤ',\n  'ⴥ' => 'Ⴥ',\n  'ⴧ' => 'Ⴧ',\n  'ⴭ' => 'Ⴭ',\n  'ꙁ' => 'Ꙁ',\n  'ꙃ' => 'Ꙃ',\n  'ꙅ' => 'Ꙅ',\n  'ꙇ' => 'Ꙇ',\n  'ꙉ' => 'Ꙉ',\n  'ꙋ' => 'Ꙋ',\n  'ꙍ' => 'Ꙍ',\n  'ꙏ' => 'Ꙏ',\n  'ꙑ' => 'Ꙑ',\n  'ꙓ' => 'Ꙓ',\n  'ꙕ' => 'Ꙕ',\n  'ꙗ' => 'Ꙗ',\n  'ꙙ' => 'Ꙙ',\n  'ꙛ' => 'Ꙛ',\n  'ꙝ' => 'Ꙝ',\n  'ꙟ' => 'Ꙟ',\n  'ꙡ' => 'Ꙡ',\n  'ꙣ' => 'Ꙣ',\n  'ꙥ' => 'Ꙥ',\n  'ꙧ' => 'Ꙧ',\n  'ꙩ' => 'Ꙩ',\n  'ꙫ' => 'Ꙫ',\n  'ꙭ' => 'Ꙭ',\n  'ꚁ' => 'Ꚁ',\n  'ꚃ' => 'Ꚃ',\n  'ꚅ' => 'Ꚅ',\n  'ꚇ' => 'Ꚇ',\n  'ꚉ' => 'Ꚉ',\n  'ꚋ' => 'Ꚋ',\n  'ꚍ' => 'Ꚍ',\n  'ꚏ' => 'Ꚏ',\n  'ꚑ' => 'Ꚑ',\n  'ꚓ' => 'Ꚓ',\n  'ꚕ' => 'Ꚕ',\n  'ꚗ' => 'Ꚗ',\n  'ꚙ' => 'Ꚙ',\n  'ꚛ' => 'Ꚛ',\n  'ꜣ' => 'Ꜣ',\n  'ꜥ' => 'Ꜥ',\n  'ꜧ' => 'Ꜧ',\n  'ꜩ' => 'Ꜩ',\n  'ꜫ' => 'Ꜫ',\n  'ꜭ' => 'Ꜭ',\n  'ꜯ' => 'Ꜯ',\n  'ꜳ' => 'Ꜳ',\n  'ꜵ' => 'Ꜵ',\n  'ꜷ' => 'Ꜷ',\n  'ꜹ' => 'Ꜹ',\n  'ꜻ' => 'Ꜻ',\n  'ꜽ' => 'Ꜽ',\n  'ꜿ' => 'Ꜿ',\n  'ꝁ' => 'Ꝁ',\n  'ꝃ' => 'Ꝃ',\n  'ꝅ' => 'Ꝅ',\n  'ꝇ' => 'Ꝇ',\n  'ꝉ' => 'Ꝉ',\n  'ꝋ' => 'Ꝋ',\n  'ꝍ' => 'Ꝍ',\n  'ꝏ' => 'Ꝏ',\n  'ꝑ' => 'Ꝑ',\n  'ꝓ' => 'Ꝓ',\n  'ꝕ' => 'Ꝕ',\n  'ꝗ' => 'Ꝗ',\n  'ꝙ' => 'Ꝙ',\n  'ꝛ' => 'Ꝛ',\n  'ꝝ' => 'Ꝝ',\n  'ꝟ' => 'Ꝟ',\n  'ꝡ' => 'Ꝡ',\n  'ꝣ' => 'Ꝣ',\n  'ꝥ' => 'Ꝥ',\n  'ꝧ' => 'Ꝧ',\n  'ꝩ' => 'Ꝩ',\n  'ꝫ' => 'Ꝫ',\n  'ꝭ' => 'Ꝭ',\n  'ꝯ' => 'Ꝯ',\n  'ꝺ' => 'Ꝺ',\n  'ꝼ' => 'Ꝼ',\n  'ꝿ' => 'Ꝿ',\n  'ꞁ' => 'Ꞁ',\n  'ꞃ' => 'Ꞃ',\n  'ꞅ' => 'Ꞅ',\n  'ꞇ' => 'Ꞇ',\n  'ꞌ' => 'Ꞌ',\n  'ꞑ' => 'Ꞑ',\n  'ꞓ' => 'Ꞓ',\n  'ꞔ' => 'Ꞔ',\n  'ꞗ' => 'Ꞗ',\n  'ꞙ' => 'Ꞙ',\n  'ꞛ' => 'Ꞛ',\n  'ꞝ' => 'Ꞝ',\n  'ꞟ' => 'Ꞟ',\n  'ꞡ' => 'Ꞡ',\n  'ꞣ' => 'Ꞣ',\n  'ꞥ' => 'Ꞥ',\n  'ꞧ' => 'Ꞧ',\n  'ꞩ' => 'Ꞩ',\n  'ꞵ' => 'Ꞵ',\n  'ꞷ' => 'Ꞷ',\n  'ꞹ' => 'Ꞹ',\n  'ꞻ' => 'Ꞻ',\n  'ꞽ' => 'Ꞽ',\n  'ꞿ' => 'Ꞿ',\n  'ꟃ' => 'Ꟃ',\n  'ꟈ' => 'Ꟈ',\n  'ꟊ' => 'Ꟊ',\n  'ꟶ' => 'Ꟶ',\n  'ꭓ' => 'Ꭓ',\n  'ꭰ' => 'Ꭰ',\n  'ꭱ' => 'Ꭱ',\n  'ꭲ' => 'Ꭲ',\n  'ꭳ' => 'Ꭳ',\n  'ꭴ' => 'Ꭴ',\n  'ꭵ' => 'Ꭵ',\n  'ꭶ' => 'Ꭶ',\n  'ꭷ' => 'Ꭷ',\n  'ꭸ' => 'Ꭸ',\n  'ꭹ' => 'Ꭹ',\n  'ꭺ' => 'Ꭺ',\n  'ꭻ' => 'Ꭻ',\n  'ꭼ' => 'Ꭼ',\n  'ꭽ' => 'Ꭽ',\n  'ꭾ' => 'Ꭾ',\n  'ꭿ' => 'Ꭿ',\n  'ꮀ' => 'Ꮀ',\n  'ꮁ' => 'Ꮁ',\n  'ꮂ' => 'Ꮂ',\n  'ꮃ' => 'Ꮃ',\n  'ꮄ' => 'Ꮄ',\n  'ꮅ' => 'Ꮅ',\n  'ꮆ' => 'Ꮆ',\n  'ꮇ' => 'Ꮇ',\n  'ꮈ' => 'Ꮈ',\n  'ꮉ' => 'Ꮉ',\n  'ꮊ' => 'Ꮊ',\n  'ꮋ' => 'Ꮋ',\n  'ꮌ' => 'Ꮌ',\n  'ꮍ' => 'Ꮍ',\n  'ꮎ' => 'Ꮎ',\n  'ꮏ' => 'Ꮏ',\n  'ꮐ' => 'Ꮐ',\n  'ꮑ' => 'Ꮑ',\n  'ꮒ' => 'Ꮒ',\n  'ꮓ' => 'Ꮓ',\n  'ꮔ' => 'Ꮔ',\n  'ꮕ' => 'Ꮕ',\n  'ꮖ' => 'Ꮖ',\n  'ꮗ' => 'Ꮗ',\n  'ꮘ' => 'Ꮘ',\n  'ꮙ' => 'Ꮙ',\n  'ꮚ' => 'Ꮚ',\n  'ꮛ' => 'Ꮛ',\n  'ꮜ' => 'Ꮜ',\n  'ꮝ' => 'Ꮝ',\n  'ꮞ' => 'Ꮞ',\n  'ꮟ' => 'Ꮟ',\n  'ꮠ' => 'Ꮠ',\n  'ꮡ' => 'Ꮡ',\n  'ꮢ' => 'Ꮢ',\n  'ꮣ' => 'Ꮣ',\n  'ꮤ' => 'Ꮤ',\n  'ꮥ' => 'Ꮥ',\n  'ꮦ' => 'Ꮦ',\n  'ꮧ' => 'Ꮧ',\n  'ꮨ' => 'Ꮨ',\n  'ꮩ' => 'Ꮩ',\n  'ꮪ' => 'Ꮪ',\n  'ꮫ' => 'Ꮫ',\n  'ꮬ' => 'Ꮬ',\n  'ꮭ' => 'Ꮭ',\n  'ꮮ' => 'Ꮮ',\n  'ꮯ' => 'Ꮯ',\n  'ꮰ' => 'Ꮰ',\n  'ꮱ' => 'Ꮱ',\n  'ꮲ' => 'Ꮲ',\n  'ꮳ' => 'Ꮳ',\n  'ꮴ' => 'Ꮴ',\n  'ꮵ' => 'Ꮵ',\n  'ꮶ' => 'Ꮶ',\n  'ꮷ' => 'Ꮷ',\n  'ꮸ' => 'Ꮸ',\n  'ꮹ' => 'Ꮹ',\n  'ꮺ' => 'Ꮺ',\n  'ꮻ' => 'Ꮻ',\n  'ꮼ' => 'Ꮼ',\n  'ꮽ' => 'Ꮽ',\n  'ꮾ' => 'Ꮾ',\n  'ꮿ' => 'Ꮿ',\n  'ａ' => 'Ａ',\n  'ｂ' => 'Ｂ',\n  'ｃ' => 'Ｃ',\n  'ｄ' => 'Ｄ',\n  'ｅ' => 'Ｅ',\n  'ｆ' => 'Ｆ',\n  'ｇ' => 'Ｇ',\n  'ｈ' => 'Ｈ',\n  'ｉ' => 'Ｉ',\n  'ｊ' => 'Ｊ',\n  'ｋ' => 'Ｋ',\n  'ｌ' => 'Ｌ',\n  'ｍ' => 'Ｍ',\n  'ｎ' => 'Ｎ',\n  'ｏ' => 'Ｏ',\n  'ｐ' => 'Ｐ',\n  'ｑ' => 'Ｑ',\n  'ｒ' => 'Ｒ',\n  'ｓ' => 'Ｓ',\n  'ｔ' => 'Ｔ',\n  'ｕ' => 'Ｕ',\n  'ｖ' => 'Ｖ',\n  'ｗ' => 'Ｗ',\n  'ｘ' => 'Ｘ',\n  'ｙ' => 'Ｙ',\n  'ｚ' => 'Ｚ',\n  '𐐨' => '𐐀',\n  '𐐩' => '𐐁',\n  '𐐪' => '𐐂',\n  '𐐫' => '𐐃',\n  '𐐬' => '𐐄',\n  '𐐭' => '𐐅',\n  '𐐮' => '𐐆',\n  '𐐯' => '𐐇',\n  '𐐰' => '𐐈',\n  '𐐱' => '𐐉',\n  '𐐲' => '𐐊',\n  '𐐳' => '𐐋',\n  '𐐴' => '𐐌',\n  '𐐵' => '𐐍',\n  '𐐶' => '𐐎',\n  '𐐷' => '𐐏',\n  '𐐸' => '𐐐',\n  '𐐹' => '𐐑',\n  '𐐺' => '𐐒',\n  '𐐻' => '𐐓',\n  '𐐼' => '𐐔',\n  '𐐽' => '𐐕',\n  '𐐾' => '𐐖',\n  '𐐿' => '𐐗',\n  '𐑀' => '𐐘',\n  '𐑁' => '𐐙',\n  '𐑂' => '𐐚',\n  '𐑃' => '𐐛',\n  '𐑄' => '𐐜',\n  '𐑅' => '𐐝',\n  '𐑆' => '𐐞',\n  '𐑇' => '𐐟',\n  '𐑈' => '𐐠',\n  '𐑉' => '𐐡',\n  '𐑊' => '𐐢',\n  '𐑋' => '𐐣',\n  '𐑌' => '𐐤',\n  '𐑍' => '𐐥',\n  '𐑎' => '𐐦',\n  '𐑏' => '𐐧',\n  '𐓘' => '𐒰',\n  '𐓙' => '𐒱',\n  '𐓚' => '𐒲',\n  '𐓛' => '𐒳',\n  '𐓜' => '𐒴',\n  '𐓝' => '𐒵',\n  '𐓞' => '𐒶',\n  '𐓟' => '𐒷',\n  '𐓠' => '𐒸',\n  '𐓡' => '𐒹',\n  '𐓢' => '𐒺',\n  '𐓣' => '𐒻',\n  '𐓤' => '𐒼',\n  '𐓥' => '𐒽',\n  '𐓦' => '𐒾',\n  '𐓧' => '𐒿',\n  '𐓨' => '𐓀',\n  '𐓩' => '𐓁',\n  '𐓪' => '𐓂',\n  '𐓫' => '𐓃',\n  '𐓬' => '𐓄',\n  '𐓭' => '𐓅',\n  '𐓮' => '𐓆',\n  '𐓯' => '𐓇',\n  '𐓰' => '𐓈',\n  '𐓱' => '𐓉',\n  '𐓲' => '𐓊',\n  '𐓳' => '𐓋',\n  '𐓴' => '𐓌',\n  '𐓵' => '𐓍',\n  '𐓶' => '𐓎',\n  '𐓷' => '𐓏',\n  '𐓸' => '𐓐',\n  '𐓹' => '𐓑',\n  '𐓺' => '𐓒',\n  '𐓻' => '𐓓',\n  '𐳀' => '𐲀',\n  '𐳁' => '𐲁',\n  '𐳂' => '𐲂',\n  '𐳃' => '𐲃',\n  '𐳄' => '𐲄',\n  '𐳅' => '𐲅',\n  '𐳆' => '𐲆',\n  '𐳇' => '𐲇',\n  '𐳈' => '𐲈',\n  '𐳉' => '𐲉',\n  '𐳊' => '𐲊',\n  '𐳋' => '𐲋',\n  '𐳌' => '𐲌',\n  '𐳍' => '𐲍',\n  '𐳎' => '𐲎',\n  '𐳏' => '𐲏',\n  '𐳐' => '𐲐',\n  '𐳑' => '𐲑',\n  '𐳒' => '𐲒',\n  '𐳓' => '𐲓',\n  '𐳔' => '𐲔',\n  '𐳕' => '𐲕',\n  '𐳖' => '𐲖',\n  '𐳗' => '𐲗',\n  '𐳘' => '𐲘',\n  '𐳙' => '𐲙',\n  '𐳚' => '𐲚',\n  '𐳛' => '𐲛',\n  '𐳜' => '𐲜',\n  '𐳝' => '𐲝',\n  '𐳞' => '𐲞',\n  '𐳟' => '𐲟',\n  '𐳠' => '𐲠',\n  '𐳡' => '𐲡',\n  '𐳢' => '𐲢',\n  '𐳣' => '𐲣',\n  '𐳤' => '𐲤',\n  '𐳥' => '𐲥',\n  '𐳦' => '𐲦',\n  '𐳧' => '𐲧',\n  '𐳨' => '𐲨',\n  '𐳩' => '𐲩',\n  '𐳪' => '𐲪',\n  '𐳫' => '𐲫',\n  '𐳬' => '𐲬',\n  '𐳭' => '𐲭',\n  '𐳮' => '𐲮',\n  '𐳯' => '𐲯',\n  '𐳰' => '𐲰',\n  '𐳱' => '𐲱',\n  '𐳲' => '𐲲',\n  '𑣀' => '𑢠',\n  '𑣁' => '𑢡',\n  '𑣂' => '𑢢',\n  '𑣃' => '𑢣',\n  '𑣄' => '𑢤',\n  '𑣅' => '𑢥',\n  '𑣆' => '𑢦',\n  '𑣇' => '𑢧',\n  '𑣈' => '𑢨',\n  '𑣉' => '𑢩',\n  '𑣊' => '𑢪',\n  '𑣋' => '𑢫',\n  '𑣌' => '𑢬',\n  '𑣍' => '𑢭',\n  '𑣎' => '𑢮',\n  '𑣏' => '𑢯',\n  '𑣐' => '𑢰',\n  '𑣑' => '𑢱',\n  '𑣒' => '𑢲',\n  '𑣓' => '𑢳',\n  '𑣔' => '𑢴',\n  '𑣕' => '𑢵',\n  '𑣖' => '𑢶',\n  '𑣗' => '𑢷',\n  '𑣘' => '𑢸',\n  '𑣙' => '𑢹',\n  '𑣚' => '𑢺',\n  '𑣛' => '𑢻',\n  '𑣜' => '𑢼',\n  '𑣝' => '𑢽',\n  '𑣞' => '𑢾',\n  '𑣟' => '𑢿',\n  '𖹠' => '𖹀',\n  '𖹡' => '𖹁',\n  '𖹢' => '𖹂',\n  '𖹣' => '𖹃',\n  '𖹤' => '𖹄',\n  '𖹥' => '𖹅',\n  '𖹦' => '𖹆',\n  '𖹧' => '𖹇',\n  '𖹨' => '𖹈',\n  '𖹩' => '𖹉',\n  '𖹪' => '𖹊',\n  '𖹫' => '𖹋',\n  '𖹬' => '𖹌',\n  '𖹭' => '𖹍',\n  '𖹮' => '𖹎',\n  '𖹯' => '𖹏',\n  '𖹰' => '𖹐',\n  '𖹱' => '𖹑',\n  '𖹲' => '𖹒',\n  '𖹳' => '𖹓',\n  '𖹴' => '𖹔',\n  '𖹵' => '𖹕',\n  '𖹶' => '𖹖',\n  '𖹷' => '𖹗',\n  '𖹸' => '𖹘',\n  '𖹹' => '𖹙',\n  '𖹺' => '𖹚',\n  '𖹻' => '𖹛',\n  '𖹼' => '𖹜',\n  '𖹽' => '𖹝',\n  '𖹾' => '𖹞',\n  '𖹿' => '𖹟',\n  '𞤢' => '𞤀',\n  '𞤣' => '𞤁',\n  '𞤤' => '𞤂',\n  '𞤥' => '𞤃',\n  '𞤦' => '𞤄',\n  '𞤧' => '𞤅',\n  '𞤨' => '𞤆',\n  '𞤩' => '𞤇',\n  '𞤪' => '𞤈',\n  '𞤫' => '𞤉',\n  '𞤬' => '𞤊',\n  '𞤭' => '𞤋',\n  '𞤮' => '𞤌',\n  '𞤯' => '𞤍',\n  '𞤰' => '𞤎',\n  '𞤱' => '𞤏',\n  '𞤲' => '𞤐',\n  '𞤳' => '𞤑',\n  '𞤴' => '𞤒',\n  '𞤵' => '𞤓',\n  '𞤶' => '𞤔',\n  '𞤷' => '𞤕',\n  '𞤸' => '𞤖',\n  '𞤹' => '𞤗',\n  '𞤺' => '𞤘',\n  '𞤻' => '𞤙',\n  '𞤼' => '𞤚',\n  '𞤽' => '𞤛',\n  '𞤾' => '𞤜',\n  '𞤿' => '𞤝',\n  '𞥀' => '𞤞',\n  '𞥁' => '𞤟',\n  '𞥂' => '𞤠',\n  '𞥃' => '𞤡',\n  'ß' => 'SS',\n  'ﬀ' => 'FF',\n  'ﬁ' => 'FI',\n  'ﬂ' => 'FL',\n  'ﬃ' => 'FFI',\n  'ﬄ' => 'FFL',\n  'ﬅ' => 'ST',\n  'ﬆ' => 'ST',\n  'և' => 'ԵՒ',\n  'ﬓ' => 'ՄՆ',\n  'ﬔ' => 'ՄԵ',\n  'ﬕ' => 'ՄԻ',\n  'ﬖ' => 'ՎՆ',\n  'ﬗ' => 'ՄԽ',\n  'ŉ' => 'ʼN',\n  'ΐ' => 'Ϊ́',\n  'ΰ' => 'Ϋ́',\n  'ǰ' => 'J̌',\n  'ẖ' => 'H̱',\n  'ẗ' => 'T̈',\n  'ẘ' => 'W̊',\n  'ẙ' => 'Y̊',\n  'ẚ' => 'Aʾ',\n  'ὐ' => 'Υ̓',\n  'ὒ' => 'Υ̓̀',\n  'ὔ' => 'Υ̓́',\n  'ὖ' => 'Υ̓͂',\n  'ᾶ' => 'Α͂',\n  'ῆ' => 'Η͂',\n  'ῒ' => 'Ϊ̀',\n  'ΐ' => 'Ϊ́',\n  'ῖ' => 'Ι͂',\n  'ῗ' => 'Ϊ͂',\n  'ῢ' => 'Ϋ̀',\n  'ΰ' => 'Ϋ́',\n  'ῤ' => 'Ρ̓',\n  'ῦ' => 'Υ͂',\n  'ῧ' => 'Ϋ͂',\n  'ῶ' => 'Ω͂',\n  'ᾈ' => 'ἈΙ',\n  'ᾉ' => 'ἉΙ',\n  'ᾊ' => 'ἊΙ',\n  'ᾋ' => 'ἋΙ',\n  'ᾌ' => 'ἌΙ',\n  'ᾍ' => 'ἍΙ',\n  'ᾎ' => 'ἎΙ',\n  'ᾏ' => 'ἏΙ',\n  'ᾘ' => 'ἨΙ',\n  'ᾙ' => 'ἩΙ',\n  'ᾚ' => 'ἪΙ',\n  'ᾛ' => 'ἫΙ',\n  'ᾜ' => 'ἬΙ',\n  'ᾝ' => 'ἭΙ',\n  'ᾞ' => 'ἮΙ',\n  'ᾟ' => 'ἯΙ',\n  'ᾨ' => 'ὨΙ',\n  'ᾩ' => 'ὩΙ',\n  'ᾪ' => 'ὪΙ',\n  'ᾫ' => 'ὫΙ',\n  'ᾬ' => 'ὬΙ',\n  'ᾭ' => 'ὭΙ',\n  'ᾮ' => 'ὮΙ',\n  'ᾯ' => 'ὯΙ',\n  'ᾼ' => 'ΑΙ',\n  'ῌ' => 'ΗΙ',\n  'ῼ' => 'ΩΙ',\n  'ᾲ' => 'ᾺΙ',\n  'ᾴ' => 'ΆΙ',\n  'ῂ' => 'ῊΙ',\n  'ῄ' => 'ΉΙ',\n  'ῲ' => 'ῺΙ',\n  'ῴ' => 'ΏΙ',\n  'ᾷ' => 'Α͂Ι',\n  'ῇ' => 'Η͂Ι',\n  'ῷ' => 'Ω͂Ι',\n);\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/bootstrap.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nuse Symfony\\Polyfill\\Mbstring as p;\n\nif (\\PHP_VERSION_ID >= 80000) {\n    return require __DIR__.'/bootstrap80.php';\n}\n\nif (!function_exists('mb_convert_encoding')) {\n    function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }\n}\nif (!function_exists('mb_decode_mimeheader')) {\n    function mb_decode_mimeheader($string) { return p\\Mbstring::mb_decode_mimeheader($string); }\n}\nif (!function_exists('mb_encode_mimeheader')) {\n    function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = \"\\r\\n\", $indent = 0) { return p\\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }\n}\nif (!function_exists('mb_decode_numericentity')) {\n    function mb_decode_numericentity($string, $map, $encoding = null) { return p\\Mbstring::mb_decode_numericentity($string, $map, $encoding); }\n}\nif (!function_exists('mb_encode_numericentity')) {\n    function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }\n}\nif (!function_exists('mb_convert_case')) {\n    function mb_convert_case($string, $mode, $encoding = null) { return p\\Mbstring::mb_convert_case($string, $mode, $encoding); }\n}\nif (!function_exists('mb_internal_encoding')) {\n    function mb_internal_encoding($encoding = null) { return p\\Mbstring::mb_internal_encoding($encoding); }\n}\nif (!function_exists('mb_language')) {\n    function mb_language($language = null) { return p\\Mbstring::mb_language($language); }\n}\nif (!function_exists('mb_list_encodings')) {\n    function mb_list_encodings() { return p\\Mbstring::mb_list_encodings(); }\n}\nif (!function_exists('mb_encoding_aliases')) {\n    function mb_encoding_aliases($encoding) { return p\\Mbstring::mb_encoding_aliases($encoding); }\n}\nif (!function_exists('mb_check_encoding')) {\n    function mb_check_encoding($value = null, $encoding = null) { return p\\Mbstring::mb_check_encoding($value, $encoding); }\n}\nif (!function_exists('mb_detect_encoding')) {\n    function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\\Mbstring::mb_detect_encoding($string, $encodings, $strict); }\n}\nif (!function_exists('mb_detect_order')) {\n    function mb_detect_order($encoding = null) { return p\\Mbstring::mb_detect_order($encoding); }\n}\nif (!function_exists('mb_parse_str')) {\n    function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }\n}\nif (!function_exists('mb_strlen')) {\n    function mb_strlen($string, $encoding = null) { return p\\Mbstring::mb_strlen($string, $encoding); }\n}\nif (!function_exists('mb_strpos')) {\n    function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }\n}\nif (!function_exists('mb_strtolower')) {\n    function mb_strtolower($string, $encoding = null) { return p\\Mbstring::mb_strtolower($string, $encoding); }\n}\nif (!function_exists('mb_strtoupper')) {\n    function mb_strtoupper($string, $encoding = null) { return p\\Mbstring::mb_strtoupper($string, $encoding); }\n}\nif (!function_exists('mb_substitute_character')) {\n    function mb_substitute_character($substitute_character = null) { return p\\Mbstring::mb_substitute_character($substitute_character); }\n}\nif (!function_exists('mb_substr')) {\n    function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\\Mbstring::mb_substr($string, $start, $length, $encoding); }\n}\nif (!function_exists('mb_stripos')) {\n    function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }\n}\nif (!function_exists('mb_stristr')) {\n    function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }\n}\nif (!function_exists('mb_strrchr')) {\n    function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }\n}\nif (!function_exists('mb_strrichr')) {\n    function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }\n}\nif (!function_exists('mb_strripos')) {\n    function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }\n}\nif (!function_exists('mb_strrpos')) {\n    function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }\n}\nif (!function_exists('mb_strstr')) {\n    function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }\n}\nif (!function_exists('mb_get_info')) {\n    function mb_get_info($type = 'all') { return p\\Mbstring::mb_get_info($type); }\n}\nif (!function_exists('mb_http_output')) {\n    function mb_http_output($encoding = null) { return p\\Mbstring::mb_http_output($encoding); }\n}\nif (!function_exists('mb_strwidth')) {\n    function mb_strwidth($string, $encoding = null) { return p\\Mbstring::mb_strwidth($string, $encoding); }\n}\nif (!function_exists('mb_substr_count')) {\n    function mb_substr_count($haystack, $needle, $encoding = null) { return p\\Mbstring::mb_substr_count($haystack, $needle, $encoding); }\n}\nif (!function_exists('mb_output_handler')) {\n    function mb_output_handler($string, $status) { return p\\Mbstring::mb_output_handler($string, $status); }\n}\nif (!function_exists('mb_http_input')) {\n    function mb_http_input($type = null) { return p\\Mbstring::mb_http_input($type); }\n}\n\nif (!function_exists('mb_convert_variables')) {\n    function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); }\n}\n\nif (!function_exists('mb_ord')) {\n    function mb_ord($string, $encoding = null) { return p\\Mbstring::mb_ord($string, $encoding); }\n}\nif (!function_exists('mb_chr')) {\n    function mb_chr($codepoint, $encoding = null) { return p\\Mbstring::mb_chr($codepoint, $encoding); }\n}\nif (!function_exists('mb_scrub')) {\n    function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }\n}\nif (!function_exists('mb_str_split')) {\n    function mb_str_split($string, $length = 1, $encoding = null) { return p\\Mbstring::mb_str_split($string, $length, $encoding); }\n}\n\nif (extension_loaded('mbstring')) {\n    return;\n}\n\nif (!defined('MB_CASE_UPPER')) {\n    define('MB_CASE_UPPER', 0);\n}\nif (!defined('MB_CASE_LOWER')) {\n    define('MB_CASE_LOWER', 1);\n}\nif (!defined('MB_CASE_TITLE')) {\n    define('MB_CASE_TITLE', 2);\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/bootstrap80.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nuse Symfony\\Polyfill\\Mbstring as p;\n\nif (!function_exists('mb_convert_encoding')) {\n    function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); }\n}\nif (!function_exists('mb_decode_mimeheader')) {\n    function mb_decode_mimeheader(?string $string): string { return p\\Mbstring::mb_decode_mimeheader((string) $string); }\n}\nif (!function_exists('mb_encode_mimeheader')) {\n    function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = \"\\r\\n\", ?int $indent = 0): string { return p\\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); }\n}\nif (!function_exists('mb_decode_numericentity')) {\n    function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); }\n}\nif (!function_exists('mb_encode_numericentity')) {\n    function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); }\n}\nif (!function_exists('mb_convert_case')) {\n    function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); }\n}\nif (!function_exists('mb_internal_encoding')) {\n    function mb_internal_encoding(?string $encoding = null): string|bool { return p\\Mbstring::mb_internal_encoding($encoding); }\n}\nif (!function_exists('mb_language')) {\n    function mb_language(?string $language = null): string|bool { return p\\Mbstring::mb_language($language); }\n}\nif (!function_exists('mb_list_encodings')) {\n    function mb_list_encodings(): array { return p\\Mbstring::mb_list_encodings(); }\n}\nif (!function_exists('mb_encoding_aliases')) {\n    function mb_encoding_aliases(?string $encoding): array { return p\\Mbstring::mb_encoding_aliases((string) $encoding); }\n}\nif (!function_exists('mb_check_encoding')) {\n    function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\\Mbstring::mb_check_encoding($value, $encoding); }\n}\nif (!function_exists('mb_detect_encoding')) {\n    function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }\n}\nif (!function_exists('mb_detect_order')) {\n    function mb_detect_order(array|string|null $encoding = null): array|bool { return p\\Mbstring::mb_detect_order($encoding); }\n}\nif (!function_exists('mb_parse_str')) {\n    function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }\n}\nif (!function_exists('mb_strlen')) {\n    function mb_strlen(?string $string, ?string $encoding = null): int { return p\\Mbstring::mb_strlen((string) $string, $encoding); }\n}\nif (!function_exists('mb_strpos')) {\n    function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }\n}\nif (!function_exists('mb_strtolower')) {\n    function mb_strtolower(?string $string, ?string $encoding = null): string { return p\\Mbstring::mb_strtolower((string) $string, $encoding); }\n}\nif (!function_exists('mb_strtoupper')) {\n    function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\\Mbstring::mb_strtoupper((string) $string, $encoding); }\n}\nif (!function_exists('mb_substitute_character')) {\n    function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\\Mbstring::mb_substitute_character($substitute_character); }\n}\nif (!function_exists('mb_substr')) {\n    function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); }\n}\nif (!function_exists('mb_stripos')) {\n    function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }\n}\nif (!function_exists('mb_stristr')) {\n    function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }\n}\nif (!function_exists('mb_strrchr')) {\n    function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }\n}\nif (!function_exists('mb_strrichr')) {\n    function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }\n}\nif (!function_exists('mb_strripos')) {\n    function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }\n}\nif (!function_exists('mb_strrpos')) {\n    function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }\n}\nif (!function_exists('mb_strstr')) {\n    function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }\n}\nif (!function_exists('mb_get_info')) {\n    function mb_get_info(?string $type = 'all'): array|string|int|false { return p\\Mbstring::mb_get_info((string) $type); }\n}\nif (!function_exists('mb_http_output')) {\n    function mb_http_output(?string $encoding = null): string|bool { return p\\Mbstring::mb_http_output($encoding); }\n}\nif (!function_exists('mb_strwidth')) {\n    function mb_strwidth(?string $string, ?string $encoding = null): int { return p\\Mbstring::mb_strwidth((string) $string, $encoding); }\n}\nif (!function_exists('mb_substr_count')) {\n    function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); }\n}\nif (!function_exists('mb_output_handler')) {\n    function mb_output_handler(?string $string, ?int $status): string { return p\\Mbstring::mb_output_handler((string) $string, (int) $status); }\n}\nif (!function_exists('mb_http_input')) {\n    function mb_http_input(?string $type = null): array|string|false { return p\\Mbstring::mb_http_input($type); }\n}\n\nif (!function_exists('mb_convert_variables')) {\n    function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); }\n}\n\nif (!function_exists('mb_ord')) {\n    function mb_ord(?string $string, ?string $encoding = null): int|false { return p\\Mbstring::mb_ord((string) $string, $encoding); }\n}\nif (!function_exists('mb_chr')) {\n    function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\\Mbstring::mb_chr((int) $codepoint, $encoding); }\n}\nif (!function_exists('mb_scrub')) {\n    function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); }\n}\nif (!function_exists('mb_str_split')) {\n    function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); }\n}\n\nif (extension_loaded('mbstring')) {\n    return;\n}\n\nif (!defined('MB_CASE_UPPER')) {\n    define('MB_CASE_UPPER', 0);\n}\nif (!defined('MB_CASE_LOWER')) {\n    define('MB_CASE_LOWER', 1);\n}\nif (!defined('MB_CASE_TITLE')) {\n    define('MB_CASE_TITLE', 2);\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-mbstring/composer.json",
    "content": "{\n    \"name\": \"symfony/polyfill-mbstring\",\n    \"type\": \"library\",\n    \"description\": \"Symfony polyfill for the Mbstring extension\",\n    \"keywords\": [\"polyfill\", \"shim\", \"compatibility\", \"portable\", \"mbstring\"],\n    \"homepage\": \"https://symfony.com\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Nicolas Grekas\",\n            \"email\": \"p@tchwork.com\"\n        },\n        {\n            \"name\": \"Symfony Community\",\n            \"homepage\": \"https://symfony.com/contributors\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.1\"\n    },\n    \"provide\": {\n        \"ext-mbstring\": \"*\"\n    },\n    \"autoload\": {\n        \"psr-4\": { \"Symfony\\\\Polyfill\\\\Mbstring\\\\\": \"\" },\n        \"files\": [ \"bootstrap.php\" ]\n    },\n    \"suggest\": {\n        \"ext-mbstring\": \"For best performance\"\n    },\n    \"minimum-stability\": \"dev\",\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-main\": \"1.23-dev\"\n        },\n        \"thanks\": {\n            \"name\": \"symfony/polyfill\",\n            \"url\": \"https://github.com/symfony/polyfill\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/LICENSE",
    "content": "Copyright (c) 2020 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/Php80.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Polyfill\\Php80;\n\n/**\n * @author Ion Bazan <ion.bazan@gmail.com>\n * @author Nico Oelgart <nicoswd@gmail.com>\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class Php80\n{\n    public static function fdiv(float $dividend, float $divisor): float\n    {\n        return @($dividend / $divisor);\n    }\n\n    public static function get_debug_type($value): string\n    {\n        switch (true) {\n            case null === $value: return 'null';\n            case \\is_bool($value): return 'bool';\n            case \\is_string($value): return 'string';\n            case \\is_array($value): return 'array';\n            case \\is_int($value): return 'int';\n            case \\is_float($value): return 'float';\n            case \\is_object($value): break;\n            case $value instanceof \\__PHP_Incomplete_Class: return '__PHP_Incomplete_Class';\n            default:\n                if (null === $type = @get_resource_type($value)) {\n                    return 'unknown';\n                }\n\n                if ('Unknown' === $type) {\n                    $type = 'closed';\n                }\n\n                return \"resource ($type)\";\n        }\n\n        $class = \\get_class($value);\n\n        if (false === strpos($class, '@')) {\n            return $class;\n        }\n\n        return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous';\n    }\n\n    public static function get_resource_id($res): int\n    {\n        if (!\\is_resource($res) && null === @get_resource_type($res)) {\n            throw new \\TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));\n        }\n\n        return (int) $res;\n    }\n\n    public static function preg_last_error_msg(): string\n    {\n        switch (preg_last_error()) {\n            case \\PREG_INTERNAL_ERROR:\n                return 'Internal error';\n            case \\PREG_BAD_UTF8_ERROR:\n                return 'Malformed UTF-8 characters, possibly incorrectly encoded';\n            case \\PREG_BAD_UTF8_OFFSET_ERROR:\n                return 'The offset did not correspond to the beginning of a valid UTF-8 code point';\n            case \\PREG_BACKTRACK_LIMIT_ERROR:\n                return 'Backtrack limit exhausted';\n            case \\PREG_RECURSION_LIMIT_ERROR:\n                return 'Recursion limit exhausted';\n            case \\PREG_JIT_STACKLIMIT_ERROR:\n                return 'JIT stack limit exhausted';\n            case \\PREG_NO_ERROR:\n                return 'No error';\n            default:\n                return 'Unknown error';\n        }\n    }\n\n    public static function str_contains(string $haystack, string $needle): bool\n    {\n        return '' === $needle || false !== strpos($haystack, $needle);\n    }\n\n    public static function str_starts_with(string $haystack, string $needle): bool\n    {\n        return 0 === strncmp($haystack, $needle, \\strlen($needle));\n    }\n\n    public static function str_ends_with(string $haystack, string $needle): bool\n    {\n        if ('' === $needle || $needle === $haystack) {\n            return true;\n        }\n\n        if ('' === $haystack) {\n            return false;\n        }\n\n        $needleLength = \\strlen($needle);\n\n        return $needleLength <= \\strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/PhpToken.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Polyfill\\Php80;\n\n/**\n * @author Fedonyuk Anton <info@ensostudio.ru>\n *\n * @internal\n */\nclass PhpToken implements \\Stringable\n{\n    /**\n     * @var int\n     */\n    public $id;\n\n    /**\n     * @var string\n     */\n    public $text;\n\n    /**\n     * @var int\n     */\n    public $line;\n\n    /**\n     * @var int\n     */\n    public $pos;\n\n    public function __construct(int $id, string $text, int $line = -1, int $position = -1)\n    {\n        $this->id = $id;\n        $this->text = $text;\n        $this->line = $line;\n        $this->pos = $position;\n    }\n\n    public function getTokenName(): ?string\n    {\n        if ('UNKNOWN' === $name = token_name($this->id)) {\n            $name = \\strlen($this->text) > 1 || \\ord($this->text) < 32 ? null : $this->text;\n        }\n\n        return $name;\n    }\n\n    /**\n     * @param int|string|array $kind\n     */\n    public function is($kind): bool\n    {\n        foreach ((array) $kind as $value) {\n            if (\\in_array($value, [$this->id, $this->text], true)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public function isIgnorable(): bool\n    {\n        return \\in_array($this->id, [\\T_WHITESPACE, \\T_COMMENT, \\T_DOC_COMMENT, \\T_OPEN_TAG], true);\n    }\n\n    public function __toString(): string\n    {\n        return (string) $this->text;\n    }\n\n    /**\n     * @return static[]\n     */\n    public static function tokenize(string $code, int $flags = 0): array\n    {\n        $line = 1;\n        $position = 0;\n        $tokens = token_get_all($code, $flags);\n        foreach ($tokens as $index => $token) {\n            if (\\is_string($token)) {\n                $id = \\ord($token);\n                $text = $token;\n            } else {\n                [$id, $text, $line] = $token;\n            }\n            $tokens[$index] = new static($id, $text, $line, $position);\n            $position += \\strlen($text);\n        }\n\n        return $tokens;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/README.md",
    "content": "Symfony Polyfill / Php80\n========================\n\nThis component provides features added to PHP 8.0 core:\n\n- `Stringable` interface\n- [`fdiv`](https://php.net/fdiv)\n- `ValueError` class\n- `UnhandledMatchError` class\n- `FILTER_VALIDATE_BOOL` constant\n- [`get_debug_type`](https://php.net/get_debug_type)\n- [`preg_last_error_msg`](https://php.net/preg_last_error_msg)\n- [`str_contains`](https://php.net/str_contains)\n- [`str_starts_with`](https://php.net/str_starts_with)\n- [`str_ends_with`](https://php.net/str_ends_with)\n- [`get_resource_id`](https://php.net/get_resource_id)\n\nMore information can be found in the\n[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).\n\nLicense\n=======\n\nThis library is released under the [MIT license](LICENSE).\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php",
    "content": "<?php\n\n#[Attribute(Attribute::TARGET_CLASS)]\nfinal class Attribute\n{\n    public const TARGET_CLASS = 1;\n    public const TARGET_FUNCTION = 2;\n    public const TARGET_METHOD = 4;\n    public const TARGET_PROPERTY = 8;\n    public const TARGET_CLASS_CONSTANT = 16;\n    public const TARGET_PARAMETER = 32;\n    public const TARGET_ALL = 63;\n    public const IS_REPEATABLE = 64;\n\n    /** @var int */\n    public $flags;\n\n    public function __construct(int $flags = self::TARGET_ALL)\n    {\n        $this->flags = $flags;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php",
    "content": "<?php\n\nif (\\PHP_VERSION_ID < 80000 && \\extension_loaded('tokenizer')) {\n    class PhpToken extends Symfony\\Polyfill\\Php80\\PhpToken\n    {\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php",
    "content": "<?php\n\nif (\\PHP_VERSION_ID < 80000) {\n    interface Stringable\n    {\n        /**\n         * @return string\n         */\n        public function __toString();\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php",
    "content": "<?php\n\nif (\\PHP_VERSION_ID < 80000) {\n    class UnhandledMatchError extends Error\n    {\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php",
    "content": "<?php\n\nif (\\PHP_VERSION_ID < 80000) {\n    class ValueError extends Error\n    {\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/bootstrap.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nuse Symfony\\Polyfill\\Php80 as p;\n\nif (\\PHP_VERSION_ID >= 80000) {\n    return;\n}\n\nif (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {\n    define('FILTER_VALIDATE_BOOL', \\FILTER_VALIDATE_BOOLEAN);\n}\n\nif (!function_exists('fdiv')) {\n    function fdiv(float $num1, float $num2): float { return p\\Php80::fdiv($num1, $num2); }\n}\nif (!function_exists('preg_last_error_msg')) {\n    function preg_last_error_msg(): string { return p\\Php80::preg_last_error_msg(); }\n}\nif (!function_exists('str_contains')) {\n    function str_contains(?string $haystack, ?string $needle): bool { return p\\Php80::str_contains($haystack ?? '', $needle ?? ''); }\n}\nif (!function_exists('str_starts_with')) {\n    function str_starts_with(?string $haystack, ?string $needle): bool { return p\\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }\n}\nif (!function_exists('str_ends_with')) {\n    function str_ends_with(?string $haystack, ?string $needle): bool { return p\\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }\n}\nif (!function_exists('get_debug_type')) {\n    function get_debug_type($value): string { return p\\Php80::get_debug_type($value); }\n}\nif (!function_exists('get_resource_id')) {\n    function get_resource_id($resource): int { return p\\Php80::get_resource_id($resource); }\n}\n"
  },
  {
    "path": "vendor/symfony/polyfill-php80/composer.json",
    "content": "{\n    \"name\": \"symfony/polyfill-php80\",\n    \"type\": \"library\",\n    \"description\": \"Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions\",\n    \"keywords\": [\"polyfill\", \"shim\", \"compatibility\", \"portable\"],\n    \"homepage\": \"https://symfony.com\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Ion Bazan\",\n            \"email\": \"ion.bazan@gmail.com\"\n        },\n        {\n            \"name\": \"Nicolas Grekas\",\n            \"email\": \"p@tchwork.com\"\n        },\n        {\n            \"name\": \"Symfony Community\",\n            \"homepage\": \"https://symfony.com/contributors\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.1\"\n    },\n    \"autoload\": {\n        \"psr-4\": { \"Symfony\\\\Polyfill\\\\Php80\\\\\": \"\" },\n        \"files\": [ \"bootstrap.php\" ],\n        \"classmap\": [ \"Resources/stubs\" ]\n    },\n    \"minimum-stability\": \"dev\",\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-main\": \"1.23-dev\"\n        },\n        \"thanks\": {\n            \"name\": \"symfony/polyfill\",\n            \"url\": \"https://github.com/symfony/polyfill\"\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/CHANGELOG.md",
    "content": "CHANGELOG\n=========\n\n5.2.0\n-----\n\n * added `Process::setOptions()` to set `Process` specific options\n * added option `create_new_console` to allow a subprocess to continue\n   to run after the main script exited, both on Linux and on Windows\n\n5.1.0\n-----\n\n * added `Process::getStartTime()` to retrieve the start time of the process as float\n\n5.0.0\n-----\n\n * removed `Process::inheritEnvironmentVariables()`\n * removed `PhpProcess::setPhpBinary()`\n * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell\n * removed `Process::setCommandLine()`\n\n4.4.0\n-----\n\n * deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited.\n * added `Process::getLastOutputTime()` method\n\n4.2.0\n-----\n\n * added the `Process::fromShellCommandline()` to run commands in a shell wrapper\n * deprecated passing a command as string when creating a `Process` instance\n * deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods\n * added the `Process::waitUntil()` method to wait for the process only for a\n   specific output, then continue the normal execution of your application\n\n4.1.0\n-----\n\n * added the `Process::isTtySupported()` method that allows to check for TTY support\n * made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary\n * added the `ProcessSignaledException` class to properly catch signaled process errors\n\n4.0.0\n-----\n\n * environment variables will always be inherited\n * added a second `array $env = []` argument to the `start()`, `run()`,\n   `mustRun()`, and `restart()` methods of the `Process` class\n * added a second `array $env = []` argument to the `start()` method of the\n   `PhpProcess` class\n * the `ProcessUtils::escapeArgument()` method has been removed\n * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()`\n   methods of the `Process` class have been removed\n * support for passing `proc_open()` options has been removed\n * removed the `ProcessBuilder` class, use the `Process` class instead\n * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class\n * passing a not existing working directory to the constructor of the `Symfony\\Component\\Process\\Process` class is not\n   supported anymore\n\n3.4.0\n-----\n\n * deprecated the ProcessBuilder class\n * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor)\n\n3.3.0\n-----\n\n * added command line arrays in the `Process` class\n * added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods\n * deprecated the `ProcessUtils::escapeArgument()` method\n * deprecated not inheriting environment variables\n * deprecated configuring `proc_open()` options\n * deprecated configuring enhanced Windows compatibility\n * deprecated configuring enhanced sigchild compatibility\n\n2.5.0\n-----\n\n * added support for PTY mode\n * added the convenience method \"mustRun\"\n * deprecation: Process::setStdin() is deprecated in favor of Process::setInput()\n * deprecation: Process::getStdin() is deprecated in favor of Process::getInput()\n * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types\n\n2.4.0\n-----\n\n * added the ability to define an idle timeout\n\n2.3.0\n-----\n\n * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows\n * added Process::signal()\n * added Process::getPid()\n * added support for a TTY mode\n\n2.2.0\n-----\n\n * added ProcessBuilder::setArguments() to reset the arguments on a builder\n * added a way to retrieve the standard and error output incrementally\n * added Process:restart()\n\n2.1.0\n-----\n\n * added support for non-blocking processes (start(), wait(), isRunning(), stop())\n * enhanced Windows compatibility\n * added Process::getExitCodeText() that returns a string representation for\n   the exit code returned by the process\n * added ProcessBuilder\n"
  },
  {
    "path": "vendor/symfony/process/Exception/ExceptionInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\n/**\n * Marker Interface for the Process Component.\n *\n * @author Johannes M. Schmitt <schmittjoh@gmail.com>\n */\ninterface ExceptionInterface extends \\Throwable\n{\n}\n"
  },
  {
    "path": "vendor/symfony/process/Exception/InvalidArgumentException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\n/**\n * InvalidArgumentException for the Process Component.\n *\n * @author Romain Neutron <imprec@gmail.com>\n */\nclass InvalidArgumentException extends \\InvalidArgumentException implements ExceptionInterface\n{\n}\n"
  },
  {
    "path": "vendor/symfony/process/Exception/LogicException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\n/**\n * LogicException for the Process Component.\n *\n * @author Romain Neutron <imprec@gmail.com>\n */\nclass LogicException extends \\LogicException implements ExceptionInterface\n{\n}\n"
  },
  {
    "path": "vendor/symfony/process/Exception/ProcessFailedException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\nuse Symfony\\Component\\Process\\Process;\n\n/**\n * Exception for failed processes.\n *\n * @author Johannes M. Schmitt <schmittjoh@gmail.com>\n */\nclass ProcessFailedException extends RuntimeException\n{\n    private $process;\n\n    public function __construct(Process $process)\n    {\n        if ($process->isSuccessful()) {\n            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');\n        }\n\n        $error = sprintf('The command \"%s\" failed.'.\"\\n\\nExit Code: %s(%s)\\n\\nWorking directory: %s\",\n            $process->getCommandLine(),\n            $process->getExitCode(),\n            $process->getExitCodeText(),\n            $process->getWorkingDirectory()\n        );\n\n        if (!$process->isOutputDisabled()) {\n            $error .= sprintf(\"\\n\\nOutput:\\n================\\n%s\\n\\nError Output:\\n================\\n%s\",\n                $process->getOutput(),\n                $process->getErrorOutput()\n            );\n        }\n\n        parent::__construct($error);\n\n        $this->process = $process;\n    }\n\n    public function getProcess()\n    {\n        return $this->process;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Exception/ProcessSignaledException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\nuse Symfony\\Component\\Process\\Process;\n\n/**\n * Exception that is thrown when a process has been signaled.\n *\n * @author Sullivan Senechal <soullivaneuh@gmail.com>\n */\nfinal class ProcessSignaledException extends RuntimeException\n{\n    private $process;\n\n    public function __construct(Process $process)\n    {\n        $this->process = $process;\n\n        parent::__construct(sprintf('The process has been signaled with signal \"%s\".', $process->getTermSignal()));\n    }\n\n    public function getProcess(): Process\n    {\n        return $this->process;\n    }\n\n    public function getSignal(): int\n    {\n        return $this->getProcess()->getTermSignal();\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Exception/ProcessTimedOutException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\nuse Symfony\\Component\\Process\\Process;\n\n/**\n * Exception that is thrown when a process times out.\n *\n * @author Johannes M. Schmitt <schmittjoh@gmail.com>\n */\nclass ProcessTimedOutException extends RuntimeException\n{\n    public const TYPE_GENERAL = 1;\n    public const TYPE_IDLE = 2;\n\n    private $process;\n    private $timeoutType;\n\n    public function __construct(Process $process, int $timeoutType)\n    {\n        $this->process = $process;\n        $this->timeoutType = $timeoutType;\n\n        parent::__construct(sprintf(\n            'The process \"%s\" exceeded the timeout of %s seconds.',\n            $process->getCommandLine(),\n            $this->getExceededTimeout()\n        ));\n    }\n\n    public function getProcess()\n    {\n        return $this->process;\n    }\n\n    public function isGeneralTimeout()\n    {\n        return self::TYPE_GENERAL === $this->timeoutType;\n    }\n\n    public function isIdleTimeout()\n    {\n        return self::TYPE_IDLE === $this->timeoutType;\n    }\n\n    public function getExceededTimeout()\n    {\n        switch ($this->timeoutType) {\n            case self::TYPE_GENERAL:\n                return $this->process->getTimeout();\n\n            case self::TYPE_IDLE:\n                return $this->process->getIdleTimeout();\n\n            default:\n                throw new \\LogicException(sprintf('Unknown timeout type \"%d\".', $this->timeoutType));\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Exception/RuntimeException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Exception;\n\n/**\n * RuntimeException for the Process Component.\n *\n * @author Johannes M. Schmitt <schmittjoh@gmail.com>\n */\nclass RuntimeException extends \\RuntimeException implements ExceptionInterface\n{\n}\n"
  },
  {
    "path": "vendor/symfony/process/ExecutableFinder.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process;\n\n/**\n * Generic executable finder.\n *\n * @author Fabien Potencier <fabien@symfony.com>\n * @author Johannes M. Schmitt <schmittjoh@gmail.com>\n */\nclass ExecutableFinder\n{\n    private $suffixes = ['.exe', '.bat', '.cmd', '.com'];\n\n    /**\n     * Replaces default suffixes of executable.\n     */\n    public function setSuffixes(array $suffixes)\n    {\n        $this->suffixes = $suffixes;\n    }\n\n    /**\n     * Adds new possible suffix to check for executable.\n     */\n    public function addSuffix(string $suffix)\n    {\n        $this->suffixes[] = $suffix;\n    }\n\n    /**\n     * Finds an executable by name.\n     *\n     * @param string      $name      The executable name (without the extension)\n     * @param string|null $default   The default to return if no executable is found\n     * @param array       $extraDirs Additional dirs to check into\n     *\n     * @return string|null\n     */\n    public function find(string $name, string $default = null, array $extraDirs = [])\n    {\n        if (ini_get('open_basedir')) {\n            $searchPath = array_merge(explode(\\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs);\n            $dirs = [];\n            foreach ($searchPath as $path) {\n                // Silencing against https://bugs.php.net/69240\n                if (@is_dir($path)) {\n                    $dirs[] = $path;\n                } else {\n                    if (basename($path) == $name && @is_executable($path)) {\n                        return $path;\n                    }\n                }\n            }\n        } else {\n            $dirs = array_merge(\n                explode(\\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),\n                $extraDirs\n            );\n        }\n\n        $suffixes = [''];\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $pathExt = getenv('PATHEXT');\n            $suffixes = array_merge($pathExt ? explode(\\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);\n        }\n        foreach ($suffixes as $suffix) {\n            foreach ($dirs as $dir) {\n                if (@is_file($file = $dir.\\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\\\' === \\DIRECTORY_SEPARATOR || @is_executable($file))) {\n                    return $file;\n                }\n            }\n        }\n\n        return $default;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/InputStream.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process;\n\nuse Symfony\\Component\\Process\\Exception\\RuntimeException;\n\n/**\n * Provides a way to continuously write to the input of a Process until the InputStream is closed.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @implements \\IteratorAggregate<int, string>\n */\nclass InputStream implements \\IteratorAggregate\n{\n    /** @var callable|null */\n    private $onEmpty = null;\n    private $input = [];\n    private $open = true;\n\n    /**\n     * Sets a callback that is called when the write buffer becomes empty.\n     */\n    public function onEmpty(callable $onEmpty = null)\n    {\n        $this->onEmpty = $onEmpty;\n    }\n\n    /**\n     * Appends an input to the write buffer.\n     *\n     * @param resource|string|int|float|bool|\\Traversable|null $input The input to append as scalar,\n     *                                                                stream resource or \\Traversable\n     */\n    public function write($input)\n    {\n        if (null === $input) {\n            return;\n        }\n        if ($this->isClosed()) {\n            throw new RuntimeException(sprintf('\"%s\" is closed.', static::class));\n        }\n        $this->input[] = ProcessUtils::validateInput(__METHOD__, $input);\n    }\n\n    /**\n     * Closes the write buffer.\n     */\n    public function close()\n    {\n        $this->open = false;\n    }\n\n    /**\n     * Tells whether the write buffer is closed or not.\n     */\n    public function isClosed()\n    {\n        return !$this->open;\n    }\n\n    /**\n     * @return \\Traversable<int, string>\n     */\n    #[\\ReturnTypeWillChange]\n    public function getIterator()\n    {\n        $this->open = true;\n\n        while ($this->open || $this->input) {\n            if (!$this->input) {\n                yield '';\n                continue;\n            }\n            $current = array_shift($this->input);\n\n            if ($current instanceof \\Iterator) {\n                yield from $current;\n            } else {\n                yield $current;\n            }\n            if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) {\n                $this->write($onEmpty($this));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/LICENSE",
    "content": "Copyright (c) 2004-2022 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/symfony/process/PhpExecutableFinder.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process;\n\n/**\n * An executable finder specifically designed for the PHP executable.\n *\n * @author Fabien Potencier <fabien@symfony.com>\n * @author Johannes M. Schmitt <schmittjoh@gmail.com>\n */\nclass PhpExecutableFinder\n{\n    private $executableFinder;\n\n    public function __construct()\n    {\n        $this->executableFinder = new ExecutableFinder();\n    }\n\n    /**\n     * Finds The PHP executable.\n     *\n     * @return string|false\n     */\n    public function find(bool $includeArgs = true)\n    {\n        if ($php = getenv('PHP_BINARY')) {\n            if (!is_executable($php)) {\n                $command = '\\\\' === \\DIRECTORY_SEPARATOR ? 'where' : 'command -v';\n                if ($php = strtok(exec($command.' '.escapeshellarg($php)), \\PHP_EOL)) {\n                    if (!is_executable($php)) {\n                        return false;\n                    }\n                } else {\n                    return false;\n                }\n            }\n\n            if (@is_dir($php)) {\n                return false;\n            }\n\n            return $php;\n        }\n\n        $args = $this->findArguments();\n        $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';\n\n        // PHP_BINARY return the current sapi executable\n        if (\\PHP_BINARY && \\in_array(\\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) {\n            return \\PHP_BINARY.$args;\n        }\n\n        if ($php = getenv('PHP_PATH')) {\n            if (!@is_executable($php) || @is_dir($php)) {\n                return false;\n            }\n\n            return $php;\n        }\n\n        if ($php = getenv('PHP_PEAR_PHP_BIN')) {\n            if (@is_executable($php) && !@is_dir($php)) {\n                return $php;\n            }\n        }\n\n        if (@is_executable($php = \\PHP_BINDIR.('\\\\' === \\DIRECTORY_SEPARATOR ? '\\\\php.exe' : '/php')) && !@is_dir($php)) {\n            return $php;\n        }\n\n        $dirs = [\\PHP_BINDIR];\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $dirs[] = 'C:\\xampp\\php\\\\';\n        }\n\n        return $this->executableFinder->find('php', false, $dirs);\n    }\n\n    /**\n     * Finds the PHP executable arguments.\n     *\n     * @return array\n     */\n    public function findArguments()\n    {\n        $arguments = [];\n        if ('phpdbg' === \\PHP_SAPI) {\n            $arguments[] = '-qrr';\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/PhpProcess.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process;\n\nuse Symfony\\Component\\Process\\Exception\\LogicException;\nuse Symfony\\Component\\Process\\Exception\\RuntimeException;\n\n/**\n * PhpProcess runs a PHP script in an independent process.\n *\n *     $p = new PhpProcess('<?php echo \"foo\"; ?>');\n *     $p->run();\n *     print $p->getOutput().\"\\n\";\n *\n * @author Fabien Potencier <fabien@symfony.com>\n */\nclass PhpProcess extends Process\n{\n    /**\n     * @param string      $script  The PHP script to run (as a string)\n     * @param string|null $cwd     The working directory or null to use the working dir of the current PHP process\n     * @param array|null  $env     The environment variables or null to use the same environment as the current PHP process\n     * @param int         $timeout The timeout in seconds\n     * @param array|null  $php     Path to the PHP binary to use with any additional arguments\n     */\n    public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null)\n    {\n        if (null === $php) {\n            $executableFinder = new PhpExecutableFinder();\n            $php = $executableFinder->find(false);\n            $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments());\n        }\n        if ('phpdbg' === \\PHP_SAPI) {\n            $file = tempnam(sys_get_temp_dir(), 'dbg');\n            file_put_contents($file, $script);\n            register_shutdown_function('unlink', $file);\n            $php[] = $file;\n            $script = null;\n        }\n\n        parent::__construct($php, $cwd, $env, $script, $timeout);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)\n    {\n        throw new LogicException(sprintf('The \"%s()\" method cannot be called when using \"%s\".', __METHOD__, self::class));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function start(callable $callback = null, array $env = [])\n    {\n        if (null === $this->getCommandLine()) {\n            throw new RuntimeException('Unable to find the PHP executable.');\n        }\n\n        parent::start($callback, $env);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Pipes/AbstractPipes.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Pipes;\n\nuse Symfony\\Component\\Process\\Exception\\InvalidArgumentException;\n\n/**\n * @author Romain Neutron <imprec@gmail.com>\n *\n * @internal\n */\nabstract class AbstractPipes implements PipesInterface\n{\n    public $pipes = [];\n\n    private $inputBuffer = '';\n    private $input;\n    private $blocked = true;\n    private $lastError;\n\n    /**\n     * @param resource|string|int|float|bool|\\Iterator|null $input\n     */\n    public function __construct($input)\n    {\n        if (\\is_resource($input) || $input instanceof \\Iterator) {\n            $this->input = $input;\n        } elseif (\\is_string($input)) {\n            $this->inputBuffer = $input;\n        } else {\n            $this->inputBuffer = (string) $input;\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function close()\n    {\n        foreach ($this->pipes as $pipe) {\n            if (\\is_resource($pipe)) {\n                fclose($pipe);\n            }\n        }\n        $this->pipes = [];\n    }\n\n    /**\n     * Returns true if a system call has been interrupted.\n     */\n    protected function hasSystemCallBeenInterrupted(): bool\n    {\n        $lastError = $this->lastError;\n        $this->lastError = null;\n\n        // stream_select returns false when the `select` system call is interrupted by an incoming signal\n        return null !== $lastError && false !== stripos($lastError, 'interrupted system call');\n    }\n\n    /**\n     * Unblocks streams.\n     */\n    protected function unblock()\n    {\n        if (!$this->blocked) {\n            return;\n        }\n\n        foreach ($this->pipes as $pipe) {\n            stream_set_blocking($pipe, 0);\n        }\n        if (\\is_resource($this->input)) {\n            stream_set_blocking($this->input, 0);\n        }\n\n        $this->blocked = false;\n    }\n\n    /**\n     * Writes input to stdin.\n     *\n     * @throws InvalidArgumentException When an input iterator yields a non supported value\n     */\n    protected function write(): ?array\n    {\n        if (!isset($this->pipes[0])) {\n            return null;\n        }\n        $input = $this->input;\n\n        if ($input instanceof \\Iterator) {\n            if (!$input->valid()) {\n                $input = null;\n            } elseif (\\is_resource($input = $input->current())) {\n                stream_set_blocking($input, 0);\n            } elseif (!isset($this->inputBuffer[0])) {\n                if (!\\is_string($input)) {\n                    if (!is_scalar($input)) {\n                        throw new InvalidArgumentException(sprintf('\"%s\" yielded a value of type \"%s\", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));\n                    }\n                    $input = (string) $input;\n                }\n                $this->inputBuffer = $input;\n                $this->input->next();\n                $input = null;\n            } else {\n                $input = null;\n            }\n        }\n\n        $r = $e = [];\n        $w = [$this->pipes[0]];\n\n        // let's have a look if something changed in streams\n        if (false === @stream_select($r, $w, $e, 0, 0)) {\n            return null;\n        }\n\n        foreach ($w as $stdin) {\n            if (isset($this->inputBuffer[0])) {\n                $written = fwrite($stdin, $this->inputBuffer);\n                $this->inputBuffer = substr($this->inputBuffer, $written);\n                if (isset($this->inputBuffer[0])) {\n                    return [$this->pipes[0]];\n                }\n            }\n\n            if ($input) {\n                while (true) {\n                    $data = fread($input, self::CHUNK_SIZE);\n                    if (!isset($data[0])) {\n                        break;\n                    }\n                    $written = fwrite($stdin, $data);\n                    $data = substr($data, $written);\n                    if (isset($data[0])) {\n                        $this->inputBuffer = $data;\n\n                        return [$this->pipes[0]];\n                    }\n                }\n                if (feof($input)) {\n                    if ($this->input instanceof \\Iterator) {\n                        $this->input->next();\n                    } else {\n                        $this->input = null;\n                    }\n                }\n            }\n        }\n\n        // no input to read on resource, buffer is empty\n        if (!isset($this->inputBuffer[0]) && !($this->input instanceof \\Iterator ? $this->input->valid() : $this->input)) {\n            $this->input = null;\n            fclose($this->pipes[0]);\n            unset($this->pipes[0]);\n        } elseif (!$w) {\n            return [$this->pipes[0]];\n        }\n\n        return null;\n    }\n\n    /**\n     * @internal\n     */\n    public function handleError(int $type, string $msg)\n    {\n        $this->lastError = $msg;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Pipes/PipesInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Pipes;\n\n/**\n * PipesInterface manages descriptors and pipes for the use of proc_open.\n *\n * @author Romain Neutron <imprec@gmail.com>\n *\n * @internal\n */\ninterface PipesInterface\n{\n    public const CHUNK_SIZE = 16384;\n\n    /**\n     * Returns an array of descriptors for the use of proc_open.\n     */\n    public function getDescriptors(): array;\n\n    /**\n     * Returns an array of filenames indexed by their related stream in case these pipes use temporary files.\n     *\n     * @return string[]\n     */\n    public function getFiles(): array;\n\n    /**\n     * Reads data in file handles and pipes.\n     *\n     * @param bool $blocking Whether to use blocking calls or not\n     * @param bool $close    Whether to close pipes if they've reached EOF\n     *\n     * @return string[] An array of read data indexed by their fd\n     */\n    public function readAndWrite(bool $blocking, bool $close = false): array;\n\n    /**\n     * Returns if the current state has open file handles or pipes.\n     */\n    public function areOpen(): bool;\n\n    /**\n     * Returns if pipes are able to read output.\n     */\n    public function haveReadSupport(): bool;\n\n    /**\n     * Closes file handles and pipes.\n     */\n    public function close();\n}\n"
  },
  {
    "path": "vendor/symfony/process/Pipes/UnixPipes.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Pipes;\n\nuse Symfony\\Component\\Process\\Process;\n\n/**\n * UnixPipes implementation uses unix pipes as handles.\n *\n * @author Romain Neutron <imprec@gmail.com>\n *\n * @internal\n */\nclass UnixPipes extends AbstractPipes\n{\n    private $ttyMode;\n    private $ptyMode;\n    private $haveReadSupport;\n\n    public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport)\n    {\n        $this->ttyMode = $ttyMode;\n        $this->ptyMode = $ptyMode;\n        $this->haveReadSupport = $haveReadSupport;\n\n        parent::__construct($input);\n    }\n\n    public function __sleep(): array\n    {\n        throw new \\BadMethodCallException('Cannot serialize '.__CLASS__);\n    }\n\n    public function __wakeup()\n    {\n        throw new \\BadMethodCallException('Cannot unserialize '.__CLASS__);\n    }\n\n    public function __destruct()\n    {\n        $this->close();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getDescriptors(): array\n    {\n        if (!$this->haveReadSupport) {\n            $nullstream = fopen('/dev/null', 'c');\n\n            return [\n                ['pipe', 'r'],\n                $nullstream,\n                $nullstream,\n            ];\n        }\n\n        if ($this->ttyMode) {\n            return [\n                ['file', '/dev/tty', 'r'],\n                ['file', '/dev/tty', 'w'],\n                ['file', '/dev/tty', 'w'],\n            ];\n        }\n\n        if ($this->ptyMode && Process::isPtySupported()) {\n            return [\n                ['pty'],\n                ['pty'],\n                ['pty'],\n            ];\n        }\n\n        return [\n            ['pipe', 'r'],\n            ['pipe', 'w'], // stdout\n            ['pipe', 'w'], // stderr\n        ];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getFiles(): array\n    {\n        return [];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function readAndWrite(bool $blocking, bool $close = false): array\n    {\n        $this->unblock();\n        $w = $this->write();\n\n        $read = $e = [];\n        $r = $this->pipes;\n        unset($r[0]);\n\n        // let's have a look if something changed in streams\n        set_error_handler([$this, 'handleError']);\n        if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {\n            restore_error_handler();\n            // if a system call has been interrupted, forget about it, let's try again\n            // otherwise, an error occurred, let's reset pipes\n            if (!$this->hasSystemCallBeenInterrupted()) {\n                $this->pipes = [];\n            }\n\n            return $read;\n        }\n        restore_error_handler();\n\n        foreach ($r as $pipe) {\n            // prior PHP 5.4 the array passed to stream_select is modified and\n            // lose key association, we have to find back the key\n            $read[$type = array_search($pipe, $this->pipes, true)] = '';\n\n            do {\n                $data = @fread($pipe, self::CHUNK_SIZE);\n                $read[$type] .= $data;\n            } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));\n\n            if (!isset($read[$type][0])) {\n                unset($read[$type]);\n            }\n\n            if ($close && feof($pipe)) {\n                fclose($pipe);\n                unset($this->pipes[$type]);\n            }\n        }\n\n        return $read;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function haveReadSupport(): bool\n    {\n        return $this->haveReadSupport;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function areOpen(): bool\n    {\n        return (bool) $this->pipes;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Pipes/WindowsPipes.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process\\Pipes;\n\nuse Symfony\\Component\\Process\\Exception\\RuntimeException;\nuse Symfony\\Component\\Process\\Process;\n\n/**\n * WindowsPipes implementation uses temporary files as handles.\n *\n * @see https://bugs.php.net/51800\n * @see https://bugs.php.net/65650\n *\n * @author Romain Neutron <imprec@gmail.com>\n *\n * @internal\n */\nclass WindowsPipes extends AbstractPipes\n{\n    private $files = [];\n    private $fileHandles = [];\n    private $lockHandles = [];\n    private $readBytes = [\n        Process::STDOUT => 0,\n        Process::STDERR => 0,\n    ];\n    private $haveReadSupport;\n\n    public function __construct($input, bool $haveReadSupport)\n    {\n        $this->haveReadSupport = $haveReadSupport;\n\n        if ($this->haveReadSupport) {\n            // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.\n            // Workaround for this problem is to use temporary files instead of pipes on Windows platform.\n            //\n            // @see https://bugs.php.net/51800\n            $pipes = [\n                Process::STDOUT => Process::OUT,\n                Process::STDERR => Process::ERR,\n            ];\n            $tmpDir = sys_get_temp_dir();\n            $lastError = 'unknown reason';\n            set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });\n            for ($i = 0;; ++$i) {\n                foreach ($pipes as $pipe => $name) {\n                    $file = sprintf('%s\\\\sf_proc_%02X.%s', $tmpDir, $i, $name);\n\n                    if (!$h = fopen($file.'.lock', 'w')) {\n                        if (file_exists($file.'.lock')) {\n                            continue 2;\n                        }\n                        restore_error_handler();\n                        throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);\n                    }\n                    if (!flock($h, \\LOCK_EX | \\LOCK_NB)) {\n                        continue 2;\n                    }\n                    if (isset($this->lockHandles[$pipe])) {\n                        flock($this->lockHandles[$pipe], \\LOCK_UN);\n                        fclose($this->lockHandles[$pipe]);\n                    }\n                    $this->lockHandles[$pipe] = $h;\n\n                    if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) {\n                        flock($this->lockHandles[$pipe], \\LOCK_UN);\n                        fclose($this->lockHandles[$pipe]);\n                        unset($this->lockHandles[$pipe]);\n                        continue 2;\n                    }\n                    $this->fileHandles[$pipe] = $h;\n                    $this->files[$pipe] = $file;\n                }\n                break;\n            }\n            restore_error_handler();\n        }\n\n        parent::__construct($input);\n    }\n\n    public function __sleep(): array\n    {\n        throw new \\BadMethodCallException('Cannot serialize '.__CLASS__);\n    }\n\n    public function __wakeup()\n    {\n        throw new \\BadMethodCallException('Cannot unserialize '.__CLASS__);\n    }\n\n    public function __destruct()\n    {\n        $this->close();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getDescriptors(): array\n    {\n        if (!$this->haveReadSupport) {\n            $nullstream = fopen('NUL', 'c');\n\n            return [\n                ['pipe', 'r'],\n                $nullstream,\n                $nullstream,\n            ];\n        }\n\n        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)\n        // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650\n        // So we redirect output within the commandline and pass the nul device to the process\n        return [\n            ['pipe', 'r'],\n            ['file', 'NUL', 'w'],\n            ['file', 'NUL', 'w'],\n        ];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getFiles(): array\n    {\n        return $this->files;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function readAndWrite(bool $blocking, bool $close = false): array\n    {\n        $this->unblock();\n        $w = $this->write();\n        $read = $r = $e = [];\n\n        if ($blocking) {\n            if ($w) {\n                @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);\n            } elseif ($this->fileHandles) {\n                usleep(Process::TIMEOUT_PRECISION * 1E6);\n            }\n        }\n        foreach ($this->fileHandles as $type => $fileHandle) {\n            $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);\n\n            if (isset($data[0])) {\n                $this->readBytes[$type] += \\strlen($data);\n                $read[$type] = $data;\n            }\n            if ($close) {\n                ftruncate($fileHandle, 0);\n                fclose($fileHandle);\n                flock($this->lockHandles[$type], \\LOCK_UN);\n                fclose($this->lockHandles[$type]);\n                unset($this->fileHandles[$type], $this->lockHandles[$type]);\n            }\n        }\n\n        return $read;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function haveReadSupport(): bool\n    {\n        return $this->haveReadSupport;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function areOpen(): bool\n    {\n        return $this->pipes && $this->fileHandles;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function close()\n    {\n        parent::close();\n        foreach ($this->fileHandles as $type => $handle) {\n            ftruncate($handle, 0);\n            fclose($handle);\n            flock($this->lockHandles[$type], \\LOCK_UN);\n            fclose($this->lockHandles[$type]);\n        }\n        $this->fileHandles = $this->lockHandles = [];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/Process.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process;\n\nuse Symfony\\Component\\Process\\Exception\\InvalidArgumentException;\nuse Symfony\\Component\\Process\\Exception\\LogicException;\nuse Symfony\\Component\\Process\\Exception\\ProcessFailedException;\nuse Symfony\\Component\\Process\\Exception\\ProcessSignaledException;\nuse Symfony\\Component\\Process\\Exception\\ProcessTimedOutException;\nuse Symfony\\Component\\Process\\Exception\\RuntimeException;\nuse Symfony\\Component\\Process\\Pipes\\PipesInterface;\nuse Symfony\\Component\\Process\\Pipes\\UnixPipes;\nuse Symfony\\Component\\Process\\Pipes\\WindowsPipes;\n\n/**\n * Process is a thin wrapper around proc_* functions to easily\n * start independent PHP processes.\n *\n * @author Fabien Potencier <fabien@symfony.com>\n * @author Romain Neutron <imprec@gmail.com>\n *\n * @implements \\IteratorAggregate<string, string>\n */\nclass Process implements \\IteratorAggregate\n{\n    public const ERR = 'err';\n    public const OUT = 'out';\n\n    public const STATUS_READY = 'ready';\n    public const STATUS_STARTED = 'started';\n    public const STATUS_TERMINATED = 'terminated';\n\n    public const STDIN = 0;\n    public const STDOUT = 1;\n    public const STDERR = 2;\n\n    // Timeout Precision in seconds.\n    public const TIMEOUT_PRECISION = 0.2;\n\n    public const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking\n    public const ITER_KEEP_OUTPUT = 2;  // By default, outputs are cleared while iterating, use this flag to keep them in memory\n    public const ITER_SKIP_OUT = 4;     // Use this flag to skip STDOUT while iterating\n    public const ITER_SKIP_ERR = 8;     // Use this flag to skip STDERR while iterating\n\n    private $callback;\n    private $hasCallback = false;\n    private $commandline;\n    private $cwd;\n    private $env;\n    private $input;\n    private $starttime;\n    private $lastOutputTime;\n    private $timeout;\n    private $idleTimeout;\n    private $exitcode;\n    private $fallbackStatus = [];\n    private $processInformation;\n    private $outputDisabled = false;\n    private $stdout;\n    private $stderr;\n    private $process;\n    private $status = self::STATUS_READY;\n    private $incrementalOutputOffset = 0;\n    private $incrementalErrorOutputOffset = 0;\n    private $tty = false;\n    private $pty;\n    private $options = ['suppress_errors' => true, 'bypass_shell' => true];\n\n    private $useFileHandles = false;\n    /** @var PipesInterface */\n    private $processPipes;\n\n    private $latestSignal;\n\n    private static $sigchild;\n\n    /**\n     * Exit codes translation table.\n     *\n     * User-defined errors must use exit codes in the 64-113 range.\n     */\n    public static $exitCodes = [\n        0 => 'OK',\n        1 => 'General error',\n        2 => 'Misuse of shell builtins',\n\n        126 => 'Invoked command cannot execute',\n        127 => 'Command not found',\n        128 => 'Invalid exit argument',\n\n        // signals\n        129 => 'Hangup',\n        130 => 'Interrupt',\n        131 => 'Quit and dump core',\n        132 => 'Illegal instruction',\n        133 => 'Trace/breakpoint trap',\n        134 => 'Process aborted',\n        135 => 'Bus error: \"access to undefined portion of memory object\"',\n        136 => 'Floating point exception: \"erroneous arithmetic operation\"',\n        137 => 'Kill (terminate immediately)',\n        138 => 'User-defined 1',\n        139 => 'Segmentation violation',\n        140 => 'User-defined 2',\n        141 => 'Write to pipe with no one reading',\n        142 => 'Signal raised by alarm',\n        143 => 'Termination (request to terminate)',\n        // 144 - not defined\n        145 => 'Child process terminated, stopped (or continued*)',\n        146 => 'Continue if stopped',\n        147 => 'Stop executing temporarily',\n        148 => 'Terminal stop signal',\n        149 => 'Background process attempting to read from tty (\"in\")',\n        150 => 'Background process attempting to write to tty (\"out\")',\n        151 => 'Urgent data available on socket',\n        152 => 'CPU time limit exceeded',\n        153 => 'File size limit exceeded',\n        154 => 'Signal raised by timer counting virtual time: \"virtual timer expired\"',\n        155 => 'Profiling timer expired',\n        // 156 - not defined\n        157 => 'Pollable event',\n        // 158 - not defined\n        159 => 'Bad syscall',\n    ];\n\n    /**\n     * @param array          $command The command to run and its arguments listed as separate entries\n     * @param string|null    $cwd     The working directory or null to use the working dir of the current PHP process\n     * @param array|null     $env     The environment variables or null to use the same environment as the current PHP process\n     * @param mixed          $input   The input as stream resource, scalar or \\Traversable, or null for no input\n     * @param int|float|null $timeout The timeout in seconds or null to disable\n     *\n     * @throws LogicException When proc_open is not installed\n     */\n    public function __construct(array $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)\n    {\n        if (!\\function_exists('proc_open')) {\n            throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.');\n        }\n\n        $this->commandline = $command;\n        $this->cwd = $cwd;\n\n        // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started\n        // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected\n        // @see : https://bugs.php.net/51800\n        // @see : https://bugs.php.net/50524\n        if (null === $this->cwd && (\\defined('ZEND_THREAD_SAFE') || '\\\\' === \\DIRECTORY_SEPARATOR)) {\n            $this->cwd = getcwd();\n        }\n        if (null !== $env) {\n            $this->setEnv($env);\n        }\n\n        $this->setInput($input);\n        $this->setTimeout($timeout);\n        $this->useFileHandles = '\\\\' === \\DIRECTORY_SEPARATOR;\n        $this->pty = false;\n    }\n\n    /**\n     * Creates a Process instance as a command-line to be run in a shell wrapper.\n     *\n     * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.)\n     * This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the\n     * shell wrapper and not to your commands.\n     *\n     * In order to inject dynamic values into command-lines, we strongly recommend using placeholders.\n     * This will save escaping values, which is not portable nor secure anyway:\n     *\n     *   $process = Process::fromShellCommandline('my_command \"${:MY_VAR}\"');\n     *   $process->run(null, ['MY_VAR' => $theValue]);\n     *\n     * @param string         $command The command line to pass to the shell of the OS\n     * @param string|null    $cwd     The working directory or null to use the working dir of the current PHP process\n     * @param array|null     $env     The environment variables or null to use the same environment as the current PHP process\n     * @param mixed          $input   The input as stream resource, scalar or \\Traversable, or null for no input\n     * @param int|float|null $timeout The timeout in seconds or null to disable\n     *\n     * @return static\n     *\n     * @throws LogicException When proc_open is not installed\n     */\n    public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)\n    {\n        $process = new static([], $cwd, $env, $input, $timeout);\n        $process->commandline = $command;\n\n        return $process;\n    }\n\n    /**\n     * @return array\n     */\n    public function __sleep()\n    {\n        throw new \\BadMethodCallException('Cannot serialize '.__CLASS__);\n    }\n\n    public function __wakeup()\n    {\n        throw new \\BadMethodCallException('Cannot unserialize '.__CLASS__);\n    }\n\n    public function __destruct()\n    {\n        if ($this->options['create_new_console'] ?? false) {\n            $this->processPipes->close();\n        } else {\n            $this->stop(0);\n        }\n    }\n\n    public function __clone()\n    {\n        $this->resetProcessData();\n    }\n\n    /**\n     * Runs the process.\n     *\n     * The callback receives the type of output (out or err) and\n     * some bytes from the output in real-time. It allows to have feedback\n     * from the independent process during execution.\n     *\n     * The STDOUT and STDERR are also available after the process is finished\n     * via the getOutput() and getErrorOutput() methods.\n     *\n     * @param callable|null $callback A PHP callback to run whenever there is some\n     *                                output available on STDOUT or STDERR\n     *\n     * @return int The exit status code\n     *\n     * @throws RuntimeException         When process can't be launched\n     * @throws RuntimeException         When process is already running\n     * @throws ProcessTimedOutException When process timed out\n     * @throws ProcessSignaledException When process stopped after receiving signal\n     * @throws LogicException           In case a callback is provided and output has been disabled\n     *\n     * @final\n     */\n    public function run(callable $callback = null, array $env = []): int\n    {\n        $this->start($callback, $env);\n\n        return $this->wait();\n    }\n\n    /**\n     * Runs the process.\n     *\n     * This is identical to run() except that an exception is thrown if the process\n     * exits with a non-zero exit code.\n     *\n     * @return $this\n     *\n     * @throws ProcessFailedException if the process didn't terminate successfully\n     *\n     * @final\n     */\n    public function mustRun(callable $callback = null, array $env = []): self\n    {\n        if (0 !== $this->run($callback, $env)) {\n            throw new ProcessFailedException($this);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Starts the process and returns after writing the input to STDIN.\n     *\n     * This method blocks until all STDIN data is sent to the process then it\n     * returns while the process runs in the background.\n     *\n     * The termination of the process can be awaited with wait().\n     *\n     * The callback receives the type of output (out or err) and some bytes from\n     * the output in real-time while writing the standard input to the process.\n     * It allows to have feedback from the independent process during execution.\n     *\n     * @param callable|null $callback A PHP callback to run whenever there is some\n     *                                output available on STDOUT or STDERR\n     *\n     * @throws RuntimeException When process can't be launched\n     * @throws RuntimeException When process is already running\n     * @throws LogicException   In case a callback is provided and output has been disabled\n     */\n    public function start(callable $callback = null, array $env = [])\n    {\n        if ($this->isRunning()) {\n            throw new RuntimeException('Process is already running.');\n        }\n\n        $this->resetProcessData();\n        $this->starttime = $this->lastOutputTime = microtime(true);\n        $this->callback = $this->buildCallback($callback);\n        $this->hasCallback = null !== $callback;\n        $descriptors = $this->getDescriptors();\n\n        if ($this->env) {\n            $env += '\\\\' === \\DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env;\n        }\n\n        $env += '\\\\' === \\DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv();\n\n        if (\\is_array($commandline = $this->commandline)) {\n            $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline));\n\n            if ('\\\\' !== \\DIRECTORY_SEPARATOR) {\n                // exec is mandatory to deal with sending a signal to the process\n                $commandline = 'exec '.$commandline;\n            }\n        } else {\n            $commandline = $this->replacePlaceholders($commandline, $env);\n        }\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $commandline = $this->prepareWindowsCommandLine($commandline, $env);\n        } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) {\n            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild\n            $descriptors[3] = ['pipe', 'w'];\n\n            // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input\n            $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';\n            $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';\n\n            // Workaround for the bug, when PTS functionality is enabled.\n            // @see : https://bugs.php.net/69442\n            $ptsWorkaround = fopen(__FILE__, 'r');\n        }\n\n        $envPairs = [];\n        foreach ($env as $k => $v) {\n            if (false !== $v && false === \\in_array($k, ['argc', 'argv', 'ARGC', 'ARGV'], true)) {\n                $envPairs[] = $k.'='.$v;\n            }\n        }\n\n        if (!is_dir($this->cwd)) {\n            throw new RuntimeException(sprintf('The provided cwd \"%s\" does not exist.', $this->cwd));\n        }\n\n        $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);\n\n        if (!\\is_resource($this->process)) {\n            throw new RuntimeException('Unable to launch a new process.');\n        }\n        $this->status = self::STATUS_STARTED;\n\n        if (isset($descriptors[3])) {\n            $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);\n        }\n\n        if ($this->tty) {\n            return;\n        }\n\n        $this->updateStatus(false);\n        $this->checkTimeout();\n    }\n\n    /**\n     * Restarts the process.\n     *\n     * Be warned that the process is cloned before being started.\n     *\n     * @param callable|null $callback A PHP callback to run whenever there is some\n     *                                output available on STDOUT or STDERR\n     *\n     * @return static\n     *\n     * @throws RuntimeException When process can't be launched\n     * @throws RuntimeException When process is already running\n     *\n     * @see start()\n     *\n     * @final\n     */\n    public function restart(callable $callback = null, array $env = []): self\n    {\n        if ($this->isRunning()) {\n            throw new RuntimeException('Process is already running.');\n        }\n\n        $process = clone $this;\n        $process->start($callback, $env);\n\n        return $process;\n    }\n\n    /**\n     * Waits for the process to terminate.\n     *\n     * The callback receives the type of output (out or err) and some bytes\n     * from the output in real-time while writing the standard input to the process.\n     * It allows to have feedback from the independent process during execution.\n     *\n     * @param callable|null $callback A valid PHP callback\n     *\n     * @return int The exitcode of the process\n     *\n     * @throws ProcessTimedOutException When process timed out\n     * @throws ProcessSignaledException When process stopped after receiving signal\n     * @throws LogicException           When process is not yet started\n     */\n    public function wait(callable $callback = null)\n    {\n        $this->requireProcessIsStarted(__FUNCTION__);\n\n        $this->updateStatus(false);\n\n        if (null !== $callback) {\n            if (!$this->processPipes->haveReadSupport()) {\n                $this->stop(0);\n                throw new LogicException('Pass the callback to the \"Process::start\" method or call enableOutput to use a callback with \"Process::wait\".');\n            }\n            $this->callback = $this->buildCallback($callback);\n        }\n\n        do {\n            $this->checkTimeout();\n            $running = '\\\\' === \\DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();\n            $this->readPipes($running, '\\\\' !== \\DIRECTORY_SEPARATOR || !$running);\n        } while ($running);\n\n        while ($this->isRunning()) {\n            $this->checkTimeout();\n            usleep(1000);\n        }\n\n        if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {\n            throw new ProcessSignaledException($this);\n        }\n\n        return $this->exitcode;\n    }\n\n    /**\n     * Waits until the callback returns true.\n     *\n     * The callback receives the type of output (out or err) and some bytes\n     * from the output in real-time while writing the standard input to the process.\n     * It allows to have feedback from the independent process during execution.\n     *\n     * @throws RuntimeException         When process timed out\n     * @throws LogicException           When process is not yet started\n     * @throws ProcessTimedOutException In case the timeout was reached\n     */\n    public function waitUntil(callable $callback): bool\n    {\n        $this->requireProcessIsStarted(__FUNCTION__);\n        $this->updateStatus(false);\n\n        if (!$this->processPipes->haveReadSupport()) {\n            $this->stop(0);\n            throw new LogicException('Pass the callback to the \"Process::start\" method or call enableOutput to use a callback with \"Process::waitUntil\".');\n        }\n        $callback = $this->buildCallback($callback);\n\n        $ready = false;\n        while (true) {\n            $this->checkTimeout();\n            $running = '\\\\' === \\DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();\n            $output = $this->processPipes->readAndWrite($running, '\\\\' !== \\DIRECTORY_SEPARATOR || !$running);\n\n            foreach ($output as $type => $data) {\n                if (3 !== $type) {\n                    $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready;\n                } elseif (!isset($this->fallbackStatus['signaled'])) {\n                    $this->fallbackStatus['exitcode'] = (int) $data;\n                }\n            }\n            if ($ready) {\n                return true;\n            }\n            if (!$running) {\n                return false;\n            }\n\n            usleep(1000);\n        }\n    }\n\n    /**\n     * Returns the Pid (process identifier), if applicable.\n     *\n     * @return int|null The process id if running, null otherwise\n     */\n    public function getPid()\n    {\n        return $this->isRunning() ? $this->processInformation['pid'] : null;\n    }\n\n    /**\n     * Sends a POSIX signal to the process.\n     *\n     * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)\n     *\n     * @return $this\n     *\n     * @throws LogicException   In case the process is not running\n     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed\n     * @throws RuntimeException In case of failure\n     */\n    public function signal(int $signal)\n    {\n        $this->doSignal($signal, true);\n\n        return $this;\n    }\n\n    /**\n     * Disables fetching output and error output from the underlying process.\n     *\n     * @return $this\n     *\n     * @throws RuntimeException In case the process is already running\n     * @throws LogicException   if an idle timeout is set\n     */\n    public function disableOutput()\n    {\n        if ($this->isRunning()) {\n            throw new RuntimeException('Disabling output while the process is running is not possible.');\n        }\n        if (null !== $this->idleTimeout) {\n            throw new LogicException('Output cannot be disabled while an idle timeout is set.');\n        }\n\n        $this->outputDisabled = true;\n\n        return $this;\n    }\n\n    /**\n     * Enables fetching output and error output from the underlying process.\n     *\n     * @return $this\n     *\n     * @throws RuntimeException In case the process is already running\n     */\n    public function enableOutput()\n    {\n        if ($this->isRunning()) {\n            throw new RuntimeException('Enabling output while the process is running is not possible.');\n        }\n\n        $this->outputDisabled = false;\n\n        return $this;\n    }\n\n    /**\n     * Returns true in case the output is disabled, false otherwise.\n     *\n     * @return bool\n     */\n    public function isOutputDisabled()\n    {\n        return $this->outputDisabled;\n    }\n\n    /**\n     * Returns the current output of the process (STDOUT).\n     *\n     * @return string\n     *\n     * @throws LogicException in case the output has been disabled\n     * @throws LogicException In case the process is not started\n     */\n    public function getOutput()\n    {\n        $this->readPipesForOutput(__FUNCTION__);\n\n        if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {\n            return '';\n        }\n\n        return $ret;\n    }\n\n    /**\n     * Returns the output incrementally.\n     *\n     * In comparison with the getOutput method which always return the whole\n     * output, this one returns the new output since the last call.\n     *\n     * @return string\n     *\n     * @throws LogicException in case the output has been disabled\n     * @throws LogicException In case the process is not started\n     */\n    public function getIncrementalOutput()\n    {\n        $this->readPipesForOutput(__FUNCTION__);\n\n        $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);\n        $this->incrementalOutputOffset = ftell($this->stdout);\n\n        if (false === $latest) {\n            return '';\n        }\n\n        return $latest;\n    }\n\n    /**\n     * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR).\n     *\n     * @param int $flags A bit field of Process::ITER_* flags\n     *\n     * @throws LogicException in case the output has been disabled\n     * @throws LogicException In case the process is not started\n     *\n     * @return \\Generator<string, string>\n     */\n    #[\\ReturnTypeWillChange]\n    public function getIterator(int $flags = 0)\n    {\n        $this->readPipesForOutput(__FUNCTION__, false);\n\n        $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags);\n        $blocking = !(self::ITER_NON_BLOCKING & $flags);\n        $yieldOut = !(self::ITER_SKIP_OUT & $flags);\n        $yieldErr = !(self::ITER_SKIP_ERR & $flags);\n\n        while (null !== $this->callback || ($yieldOut && !feof($this->stdout)) || ($yieldErr && !feof($this->stderr))) {\n            if ($yieldOut) {\n                $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);\n\n                if (isset($out[0])) {\n                    if ($clearOutput) {\n                        $this->clearOutput();\n                    } else {\n                        $this->incrementalOutputOffset = ftell($this->stdout);\n                    }\n\n                    yield self::OUT => $out;\n                }\n            }\n\n            if ($yieldErr) {\n                $err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);\n\n                if (isset($err[0])) {\n                    if ($clearOutput) {\n                        $this->clearErrorOutput();\n                    } else {\n                        $this->incrementalErrorOutputOffset = ftell($this->stderr);\n                    }\n\n                    yield self::ERR => $err;\n                }\n            }\n\n            if (!$blocking && !isset($out[0]) && !isset($err[0])) {\n                yield self::OUT => '';\n            }\n\n            $this->checkTimeout();\n            $this->readPipesForOutput(__FUNCTION__, $blocking);\n        }\n    }\n\n    /**\n     * Clears the process output.\n     *\n     * @return $this\n     */\n    public function clearOutput()\n    {\n        ftruncate($this->stdout, 0);\n        fseek($this->stdout, 0);\n        $this->incrementalOutputOffset = 0;\n\n        return $this;\n    }\n\n    /**\n     * Returns the current error output of the process (STDERR).\n     *\n     * @return string\n     *\n     * @throws LogicException in case the output has been disabled\n     * @throws LogicException In case the process is not started\n     */\n    public function getErrorOutput()\n    {\n        $this->readPipesForOutput(__FUNCTION__);\n\n        if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {\n            return '';\n        }\n\n        return $ret;\n    }\n\n    /**\n     * Returns the errorOutput incrementally.\n     *\n     * In comparison with the getErrorOutput method which always return the\n     * whole error output, this one returns the new error output since the last\n     * call.\n     *\n     * @return string\n     *\n     * @throws LogicException in case the output has been disabled\n     * @throws LogicException In case the process is not started\n     */\n    public function getIncrementalErrorOutput()\n    {\n        $this->readPipesForOutput(__FUNCTION__);\n\n        $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);\n        $this->incrementalErrorOutputOffset = ftell($this->stderr);\n\n        if (false === $latest) {\n            return '';\n        }\n\n        return $latest;\n    }\n\n    /**\n     * Clears the process output.\n     *\n     * @return $this\n     */\n    public function clearErrorOutput()\n    {\n        ftruncate($this->stderr, 0);\n        fseek($this->stderr, 0);\n        $this->incrementalErrorOutputOffset = 0;\n\n        return $this;\n    }\n\n    /**\n     * Returns the exit code returned by the process.\n     *\n     * @return int|null The exit status code, null if the Process is not terminated\n     */\n    public function getExitCode()\n    {\n        $this->updateStatus(false);\n\n        return $this->exitcode;\n    }\n\n    /**\n     * Returns a string representation for the exit code returned by the process.\n     *\n     * This method relies on the Unix exit code status standardization\n     * and might not be relevant for other operating systems.\n     *\n     * @return string|null A string representation for the exit status code, null if the Process is not terminated\n     *\n     * @see http://tldp.org/LDP/abs/html/exitcodes.html\n     * @see http://en.wikipedia.org/wiki/Unix_signal\n     */\n    public function getExitCodeText()\n    {\n        if (null === $exitcode = $this->getExitCode()) {\n            return null;\n        }\n\n        return self::$exitCodes[$exitcode] ?? 'Unknown error';\n    }\n\n    /**\n     * Checks if the process ended successfully.\n     *\n     * @return bool\n     */\n    public function isSuccessful()\n    {\n        return 0 === $this->getExitCode();\n    }\n\n    /**\n     * Returns true if the child process has been terminated by an uncaught signal.\n     *\n     * It always returns false on Windows.\n     *\n     * @return bool\n     *\n     * @throws LogicException In case the process is not terminated\n     */\n    public function hasBeenSignaled()\n    {\n        $this->requireProcessIsTerminated(__FUNCTION__);\n\n        return $this->processInformation['signaled'];\n    }\n\n    /**\n     * Returns the number of the signal that caused the child process to terminate its execution.\n     *\n     * It is only meaningful if hasBeenSignaled() returns true.\n     *\n     * @return int\n     *\n     * @throws RuntimeException In case --enable-sigchild is activated\n     * @throws LogicException   In case the process is not terminated\n     */\n    public function getTermSignal()\n    {\n        $this->requireProcessIsTerminated(__FUNCTION__);\n\n        if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) {\n            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.');\n        }\n\n        return $this->processInformation['termsig'];\n    }\n\n    /**\n     * Returns true if the child process has been stopped by a signal.\n     *\n     * It always returns false on Windows.\n     *\n     * @return bool\n     *\n     * @throws LogicException In case the process is not terminated\n     */\n    public function hasBeenStopped()\n    {\n        $this->requireProcessIsTerminated(__FUNCTION__);\n\n        return $this->processInformation['stopped'];\n    }\n\n    /**\n     * Returns the number of the signal that caused the child process to stop its execution.\n     *\n     * It is only meaningful if hasBeenStopped() returns true.\n     *\n     * @return int\n     *\n     * @throws LogicException In case the process is not terminated\n     */\n    public function getStopSignal()\n    {\n        $this->requireProcessIsTerminated(__FUNCTION__);\n\n        return $this->processInformation['stopsig'];\n    }\n\n    /**\n     * Checks if the process is currently running.\n     *\n     * @return bool\n     */\n    public function isRunning()\n    {\n        if (self::STATUS_STARTED !== $this->status) {\n            return false;\n        }\n\n        $this->updateStatus(false);\n\n        return $this->processInformation['running'];\n    }\n\n    /**\n     * Checks if the process has been started with no regard to the current state.\n     *\n     * @return bool\n     */\n    public function isStarted()\n    {\n        return self::STATUS_READY != $this->status;\n    }\n\n    /**\n     * Checks if the process is terminated.\n     *\n     * @return bool\n     */\n    public function isTerminated()\n    {\n        $this->updateStatus(false);\n\n        return self::STATUS_TERMINATED == $this->status;\n    }\n\n    /**\n     * Gets the process status.\n     *\n     * The status is one of: ready, started, terminated.\n     *\n     * @return string\n     */\n    public function getStatus()\n    {\n        $this->updateStatus(false);\n\n        return $this->status;\n    }\n\n    /**\n     * Stops the process.\n     *\n     * @param int|float $timeout The timeout in seconds\n     * @param int       $signal  A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9)\n     *\n     * @return int|null The exit-code of the process or null if it's not running\n     */\n    public function stop(float $timeout = 10, int $signal = null)\n    {\n        $timeoutMicro = microtime(true) + $timeout;\n        if ($this->isRunning()) {\n            // given SIGTERM may not be defined and that \"proc_terminate\" uses the constant value and not the constant itself, we use the same here\n            $this->doSignal(15, false);\n            do {\n                usleep(1000);\n            } while ($this->isRunning() && microtime(true) < $timeoutMicro);\n\n            if ($this->isRunning()) {\n                // Avoid exception here: process is supposed to be running, but it might have stopped just\n                // after this line. In any case, let's silently discard the error, we cannot do anything.\n                $this->doSignal($signal ?: 9, false);\n            }\n        }\n\n        if ($this->isRunning()) {\n            if (isset($this->fallbackStatus['pid'])) {\n                unset($this->fallbackStatus['pid']);\n\n                return $this->stop(0, $signal);\n            }\n            $this->close();\n        }\n\n        return $this->exitcode;\n    }\n\n    /**\n     * Adds a line to the STDOUT stream.\n     *\n     * @internal\n     */\n    public function addOutput(string $line)\n    {\n        $this->lastOutputTime = microtime(true);\n\n        fseek($this->stdout, 0, \\SEEK_END);\n        fwrite($this->stdout, $line);\n        fseek($this->stdout, $this->incrementalOutputOffset);\n    }\n\n    /**\n     * Adds a line to the STDERR stream.\n     *\n     * @internal\n     */\n    public function addErrorOutput(string $line)\n    {\n        $this->lastOutputTime = microtime(true);\n\n        fseek($this->stderr, 0, \\SEEK_END);\n        fwrite($this->stderr, $line);\n        fseek($this->stderr, $this->incrementalErrorOutputOffset);\n    }\n\n    /**\n     * Gets the last output time in seconds.\n     */\n    public function getLastOutputTime(): ?float\n    {\n        return $this->lastOutputTime;\n    }\n\n    /**\n     * Gets the command line to be executed.\n     *\n     * @return string\n     */\n    public function getCommandLine()\n    {\n        return \\is_array($this->commandline) ? implode(' ', array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline;\n    }\n\n    /**\n     * Gets the process timeout in seconds (max. runtime).\n     *\n     * @return float|null\n     */\n    public function getTimeout()\n    {\n        return $this->timeout;\n    }\n\n    /**\n     * Gets the process idle timeout in seconds (max. time since last output).\n     *\n     * @return float|null\n     */\n    public function getIdleTimeout()\n    {\n        return $this->idleTimeout;\n    }\n\n    /**\n     * Sets the process timeout (max. runtime) in seconds.\n     *\n     * To disable the timeout, set this value to null.\n     *\n     * @return $this\n     *\n     * @throws InvalidArgumentException if the timeout is negative\n     */\n    public function setTimeout(?float $timeout)\n    {\n        $this->timeout = $this->validateTimeout($timeout);\n\n        return $this;\n    }\n\n    /**\n     * Sets the process idle timeout (max. time since last output) in seconds.\n     *\n     * To disable the timeout, set this value to null.\n     *\n     * @return $this\n     *\n     * @throws LogicException           if the output is disabled\n     * @throws InvalidArgumentException if the timeout is negative\n     */\n    public function setIdleTimeout(?float $timeout)\n    {\n        if (null !== $timeout && $this->outputDisabled) {\n            throw new LogicException('Idle timeout cannot be set while the output is disabled.');\n        }\n\n        $this->idleTimeout = $this->validateTimeout($timeout);\n\n        return $this;\n    }\n\n    /**\n     * Enables or disables the TTY mode.\n     *\n     * @return $this\n     *\n     * @throws RuntimeException In case the TTY mode is not supported\n     */\n    public function setTty(bool $tty)\n    {\n        if ('\\\\' === \\DIRECTORY_SEPARATOR && $tty) {\n            throw new RuntimeException('TTY mode is not supported on Windows platform.');\n        }\n\n        if ($tty && !self::isTtySupported()) {\n            throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');\n        }\n\n        $this->tty = $tty;\n\n        return $this;\n    }\n\n    /**\n     * Checks if the TTY mode is enabled.\n     *\n     * @return bool\n     */\n    public function isTty()\n    {\n        return $this->tty;\n    }\n\n    /**\n     * Sets PTY mode.\n     *\n     * @return $this\n     */\n    public function setPty(bool $bool)\n    {\n        $this->pty = $bool;\n\n        return $this;\n    }\n\n    /**\n     * Returns PTY state.\n     *\n     * @return bool\n     */\n    public function isPty()\n    {\n        return $this->pty;\n    }\n\n    /**\n     * Gets the working directory.\n     *\n     * @return string|null\n     */\n    public function getWorkingDirectory()\n    {\n        if (null === $this->cwd) {\n            // getcwd() will return false if any one of the parent directories does not have\n            // the readable or search mode set, even if the current directory does\n            return getcwd() ?: null;\n        }\n\n        return $this->cwd;\n    }\n\n    /**\n     * Sets the current working directory.\n     *\n     * @return $this\n     */\n    public function setWorkingDirectory(string $cwd)\n    {\n        $this->cwd = $cwd;\n\n        return $this;\n    }\n\n    /**\n     * Gets the environment variables.\n     *\n     * @return array\n     */\n    public function getEnv()\n    {\n        return $this->env;\n    }\n\n    /**\n     * Sets the environment variables.\n     *\n     * @param array<string|\\Stringable> $env The new environment variables\n     *\n     * @return $this\n     */\n    public function setEnv(array $env)\n    {\n        $this->env = $env;\n\n        return $this;\n    }\n\n    /**\n     * Gets the Process input.\n     *\n     * @return resource|string|\\Iterator|null\n     */\n    public function getInput()\n    {\n        return $this->input;\n    }\n\n    /**\n     * Sets the input.\n     *\n     * This content will be passed to the underlying process standard input.\n     *\n     * @param string|int|float|bool|resource|\\Traversable|null $input The content\n     *\n     * @return $this\n     *\n     * @throws LogicException In case the process is running\n     */\n    public function setInput($input)\n    {\n        if ($this->isRunning()) {\n            throw new LogicException('Input cannot be set while the process is running.');\n        }\n\n        $this->input = ProcessUtils::validateInput(__METHOD__, $input);\n\n        return $this;\n    }\n\n    /**\n     * Performs a check between the timeout definition and the time the process started.\n     *\n     * In case you run a background process (with the start method), you should\n     * trigger this method regularly to ensure the process timeout\n     *\n     * @throws ProcessTimedOutException In case the timeout was reached\n     */\n    public function checkTimeout()\n    {\n        if (self::STATUS_STARTED !== $this->status) {\n            return;\n        }\n\n        if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {\n            $this->stop(0);\n\n            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);\n        }\n\n        if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {\n            $this->stop(0);\n\n            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);\n        }\n    }\n\n    /**\n     * @throws LogicException in case process is not started\n     */\n    public function getStartTime(): float\n    {\n        if (!$this->isStarted()) {\n            throw new LogicException('Start time is only available after process start.');\n        }\n\n        return $this->starttime;\n    }\n\n    /**\n     * Defines options to pass to the underlying proc_open().\n     *\n     * @see https://php.net/proc_open for the options supported by PHP.\n     *\n     * Enabling the \"create_new_console\" option allows a subprocess to continue\n     * to run after the main process exited, on both Windows and *nix\n     */\n    public function setOptions(array $options)\n    {\n        if ($this->isRunning()) {\n            throw new RuntimeException('Setting options while the process is running is not possible.');\n        }\n\n        $defaultOptions = $this->options;\n        $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console'];\n\n        foreach ($options as $key => $value) {\n            if (!\\in_array($key, $existingOptions)) {\n                $this->options = $defaultOptions;\n                throw new LogicException(sprintf('Invalid option \"%s\" passed to \"%s()\". Supported options are \"%s\".', $key, __METHOD__, implode('\", \"', $existingOptions)));\n            }\n            $this->options[$key] = $value;\n        }\n    }\n\n    /**\n     * Returns whether TTY is supported on the current operating system.\n     */\n    public static function isTtySupported(): bool\n    {\n        static $isTtySupported;\n\n        if (null === $isTtySupported) {\n            $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes);\n        }\n\n        return $isTtySupported;\n    }\n\n    /**\n     * Returns whether PTY is supported on the current operating system.\n     *\n     * @return bool\n     */\n    public static function isPtySupported()\n    {\n        static $result;\n\n        if (null !== $result) {\n            return $result;\n        }\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            return $result = false;\n        }\n\n        return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes);\n    }\n\n    /**\n     * Creates the descriptors needed by the proc_open.\n     */\n    private function getDescriptors(): array\n    {\n        if ($this->input instanceof \\Iterator) {\n            $this->input->rewind();\n        }\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback);\n        } else {\n            $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback);\n        }\n\n        return $this->processPipes->getDescriptors();\n    }\n\n    /**\n     * Builds up the callback used by wait().\n     *\n     * The callbacks adds all occurred output to the specific buffer and calls\n     * the user callback (if present) with the received output.\n     *\n     * @param callable|null $callback The user defined PHP callback\n     *\n     * @return \\Closure\n     */\n    protected function buildCallback(callable $callback = null)\n    {\n        if ($this->outputDisabled) {\n            return function ($type, $data) use ($callback): bool {\n                return null !== $callback && $callback($type, $data);\n            };\n        }\n\n        $out = self::OUT;\n\n        return function ($type, $data) use ($callback, $out): bool {\n            if ($out == $type) {\n                $this->addOutput($data);\n            } else {\n                $this->addErrorOutput($data);\n            }\n\n            return null !== $callback && $callback($type, $data);\n        };\n    }\n\n    /**\n     * Updates the status of the process, reads pipes.\n     *\n     * @param bool $blocking Whether to use a blocking read call\n     */\n    protected function updateStatus(bool $blocking)\n    {\n        if (self::STATUS_STARTED !== $this->status) {\n            return;\n        }\n\n        $this->processInformation = proc_get_status($this->process);\n        $running = $this->processInformation['running'];\n\n        $this->readPipes($running && $blocking, '\\\\' !== \\DIRECTORY_SEPARATOR || !$running);\n\n        if ($this->fallbackStatus && $this->isSigchildEnabled()) {\n            $this->processInformation = $this->fallbackStatus + $this->processInformation;\n        }\n\n        if (!$running) {\n            $this->close();\n        }\n    }\n\n    /**\n     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.\n     *\n     * @return bool\n     */\n    protected function isSigchildEnabled()\n    {\n        if (null !== self::$sigchild) {\n            return self::$sigchild;\n        }\n\n        if (!\\function_exists('phpinfo')) {\n            return self::$sigchild = false;\n        }\n\n        ob_start();\n        phpinfo(\\INFO_GENERAL);\n\n        return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild');\n    }\n\n    /**\n     * Reads pipes for the freshest output.\n     *\n     * @param string $caller   The name of the method that needs fresh outputs\n     * @param bool   $blocking Whether to use blocking calls or not\n     *\n     * @throws LogicException in case output has been disabled or process is not started\n     */\n    private function readPipesForOutput(string $caller, bool $blocking = false)\n    {\n        if ($this->outputDisabled) {\n            throw new LogicException('Output has been disabled.');\n        }\n\n        $this->requireProcessIsStarted($caller);\n\n        $this->updateStatus($blocking);\n    }\n\n    /**\n     * Validates and returns the filtered timeout.\n     *\n     * @throws InvalidArgumentException if the given timeout is a negative number\n     */\n    private function validateTimeout(?float $timeout): ?float\n    {\n        $timeout = (float) $timeout;\n\n        if (0.0 === $timeout) {\n            $timeout = null;\n        } elseif ($timeout < 0) {\n            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');\n        }\n\n        return $timeout;\n    }\n\n    /**\n     * Reads pipes, executes callback.\n     *\n     * @param bool $blocking Whether to use blocking calls or not\n     * @param bool $close    Whether to close file handles or not\n     */\n    private function readPipes(bool $blocking, bool $close)\n    {\n        $result = $this->processPipes->readAndWrite($blocking, $close);\n\n        $callback = $this->callback;\n        foreach ($result as $type => $data) {\n            if (3 !== $type) {\n                $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);\n            } elseif (!isset($this->fallbackStatus['signaled'])) {\n                $this->fallbackStatus['exitcode'] = (int) $data;\n            }\n        }\n    }\n\n    /**\n     * Closes process resource, closes file handles, sets the exitcode.\n     *\n     * @return int The exitcode\n     */\n    private function close(): int\n    {\n        $this->processPipes->close();\n        if (\\is_resource($this->process)) {\n            proc_close($this->process);\n        }\n        $this->exitcode = $this->processInformation['exitcode'];\n        $this->status = self::STATUS_TERMINATED;\n\n        if (-1 === $this->exitcode) {\n            if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {\n                // if process has been signaled, no exitcode but a valid termsig, apply Unix convention\n                $this->exitcode = 128 + $this->processInformation['termsig'];\n            } elseif ($this->isSigchildEnabled()) {\n                $this->processInformation['signaled'] = true;\n                $this->processInformation['termsig'] = -1;\n            }\n        }\n\n        // Free memory from self-reference callback created by buildCallback\n        // Doing so in other contexts like __destruct or by garbage collector is ineffective\n        // Now pipes are closed, so the callback is no longer necessary\n        $this->callback = null;\n\n        return $this->exitcode;\n    }\n\n    /**\n     * Resets data related to the latest run of the process.\n     */\n    private function resetProcessData()\n    {\n        $this->starttime = null;\n        $this->callback = null;\n        $this->exitcode = null;\n        $this->fallbackStatus = [];\n        $this->processInformation = null;\n        $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+');\n        $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+');\n        $this->process = null;\n        $this->latestSignal = null;\n        $this->status = self::STATUS_READY;\n        $this->incrementalOutputOffset = 0;\n        $this->incrementalErrorOutputOffset = 0;\n    }\n\n    /**\n     * Sends a POSIX signal to the process.\n     *\n     * @param int  $signal         A valid POSIX signal (see https://php.net/pcntl.constants)\n     * @param bool $throwException Whether to throw exception in case signal failed\n     *\n     * @throws LogicException   In case the process is not running\n     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed\n     * @throws RuntimeException In case of failure\n     */\n    private function doSignal(int $signal, bool $throwException): bool\n    {\n        if (null === $pid = $this->getPid()) {\n            if ($throwException) {\n                throw new LogicException('Cannot send signal on a non running process.');\n            }\n\n            return false;\n        }\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR) {\n            exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);\n            if ($exitCode && $this->isRunning()) {\n                if ($throwException) {\n                    throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));\n                }\n\n                return false;\n            }\n        } else {\n            if (!$this->isSigchildEnabled()) {\n                $ok = @proc_terminate($this->process, $signal);\n            } elseif (\\function_exists('posix_kill')) {\n                $ok = @posix_kill($pid, $signal);\n            } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {\n                $ok = false === fgets($pipes[2]);\n            }\n            if (!$ok) {\n                if ($throwException) {\n                    throw new RuntimeException(sprintf('Error while sending signal \"%s\".', $signal));\n                }\n\n                return false;\n            }\n        }\n\n        $this->latestSignal = $signal;\n        $this->fallbackStatus['signaled'] = true;\n        $this->fallbackStatus['exitcode'] = -1;\n        $this->fallbackStatus['termsig'] = $this->latestSignal;\n\n        return true;\n    }\n\n    private function prepareWindowsCommandLine(string $cmd, array &$env): string\n    {\n        $uid = uniqid('', true);\n        $varCount = 0;\n        $varCache = [];\n        $cmd = preg_replace_callback(\n            '/\"(?:(\n                [^\"%!^]*+\n                (?:\n                    (?: !LF! | \"(?:\\^[%!^])?+\" )\n                    [^\"%!^]*+\n                )++\n            ) | [^\"]*+ )\"/x',\n            function ($m) use (&$env, &$varCache, &$varCount, $uid) {\n                if (!isset($m[1])) {\n                    return $m[0];\n                }\n                if (isset($varCache[$m[0]])) {\n                    return $varCache[$m[0]];\n                }\n                if (str_contains($value = $m[1], \"\\0\")) {\n                    $value = str_replace(\"\\0\", '?', $value);\n                }\n                if (false === strpbrk($value, \"\\\"%!\\n\")) {\n                    return '\"'.$value.'\"';\n                }\n\n                $value = str_replace(['!LF!', '\"^!\"', '\"^%\"', '\"^^\"', '\"\"'], [\"\\n\", '!', '%', '^', '\"'], $value);\n                $value = '\"'.preg_replace('/(\\\\\\\\*)\"/', '$1$1\\\\\"', $value).'\"';\n                $var = $uid.++$varCount;\n\n                $env[$var] = $value;\n\n                return $varCache[$m[0]] = '!'.$var.'!';\n            },\n            $cmd\n        );\n\n        $cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace(\"\\n\", ' ', $cmd).')';\n        foreach ($this->processPipes->getFiles() as $offset => $filename) {\n            $cmd .= ' '.$offset.'>\"'.$filename.'\"';\n        }\n\n        return $cmd;\n    }\n\n    /**\n     * Ensures the process is running or terminated, throws a LogicException if the process has a not started.\n     *\n     * @throws LogicException if the process has not run\n     */\n    private function requireProcessIsStarted(string $functionName)\n    {\n        if (!$this->isStarted()) {\n            throw new LogicException(sprintf('Process must be started before calling \"%s()\".', $functionName));\n        }\n    }\n\n    /**\n     * Ensures the process is terminated, throws a LogicException if the process has a status different than \"terminated\".\n     *\n     * @throws LogicException if the process is not yet terminated\n     */\n    private function requireProcessIsTerminated(string $functionName)\n    {\n        if (!$this->isTerminated()) {\n            throw new LogicException(sprintf('Process must be terminated before calling \"%s()\".', $functionName));\n        }\n    }\n\n    /**\n     * Escapes a string to be used as a shell argument.\n     */\n    private function escapeArgument(?string $argument): string\n    {\n        if ('' === $argument || null === $argument) {\n            return '\"\"';\n        }\n        if ('\\\\' !== \\DIRECTORY_SEPARATOR) {\n            return \"'\".str_replace(\"'\", \"'\\\\''\", $argument).\"'\";\n        }\n        if (str_contains($argument, \"\\0\")) {\n            $argument = str_replace(\"\\0\", '?', $argument);\n        }\n        if (!preg_match('/[\\/()%!^\"<>&|\\s]/', $argument)) {\n            return $argument;\n        }\n        $argument = preg_replace('/(\\\\\\\\+)$/', '$1$1', $argument);\n\n        return '\"'.str_replace(['\"', '^', '%', '!', \"\\n\"], ['\"\"', '\"^^\"', '\"^%\"', '\"^!\"', '!LF!'], $argument).'\"';\n    }\n\n    private function replacePlaceholders(string $commandline, array $env)\n    {\n        return preg_replace_callback('/\"\\$\\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\\}\"/', function ($matches) use ($commandline, $env) {\n            if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) {\n                throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter \"%s\": ', $matches[1]).$commandline);\n            }\n\n            return $this->escapeArgument($env[$matches[1]]);\n        }, $commandline);\n    }\n\n    private function getDefaultEnv(): array\n    {\n        $env = getenv();\n        $env = ('\\\\' === \\DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env;\n\n        return $_ENV + ('\\\\' === \\DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/ProcessUtils.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\Process;\n\nuse Symfony\\Component\\Process\\Exception\\InvalidArgumentException;\n\n/**\n * ProcessUtils is a bunch of utility methods.\n *\n * This class contains static methods only and is not meant to be instantiated.\n *\n * @author Martin Hasoň <martin.hason@gmail.com>\n */\nclass ProcessUtils\n{\n    /**\n     * This class should not be instantiated.\n     */\n    private function __construct()\n    {\n    }\n\n    /**\n     * Validates and normalizes a Process input.\n     *\n     * @param string $caller The name of method call that validates the input\n     * @param mixed  $input  The input to validate\n     *\n     * @return mixed\n     *\n     * @throws InvalidArgumentException In case the input is not valid\n     */\n    public static function validateInput(string $caller, $input)\n    {\n        if (null !== $input) {\n            if (\\is_resource($input)) {\n                return $input;\n            }\n            if (\\is_string($input)) {\n                return $input;\n            }\n            if (is_scalar($input)) {\n                return (string) $input;\n            }\n            if ($input instanceof Process) {\n                return $input->getIterator($input::ITER_SKIP_ERR);\n            }\n            if ($input instanceof \\Iterator) {\n                return $input;\n            }\n            if ($input instanceof \\Traversable) {\n                return new \\IteratorIterator($input);\n            }\n\n            throw new InvalidArgumentException(sprintf('\"%s\" only accepts strings, Traversable objects or stream resources.', $caller));\n        }\n\n        return $input;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/process/README.md",
    "content": "Process Component\n=================\n\nThe Process component executes commands in sub-processes.\n\nSponsor\n-------\n\nThe Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2].\n\nAs the creator of Symfony, SensioLabs supports companies using Symfony, with an\noffering encompassing consultancy, expertise, services, training, and technical\nassistance to ensure the success of web application development projects.\n\nHelp Symfony by [sponsoring][3] its development!\n\nResources\n---------\n\n * [Documentation](https://symfony.com/doc/current/components/process.html)\n * [Contributing](https://symfony.com/doc/current/contributing/index.html)\n * [Report issues](https://github.com/symfony/symfony/issues) and\n   [send Pull Requests](https://github.com/symfony/symfony/pulls)\n   in the [main Symfony repository](https://github.com/symfony/symfony)\n\n[1]: https://symfony.com/backers\n[2]: https://sensiolabs.com\n[3]: https://symfony.com/sponsor\n"
  },
  {
    "path": "vendor/symfony/process/composer.json",
    "content": "{\n    \"name\": \"symfony/process\",\n    \"type\": \"library\",\n    \"description\": \"Executes commands in sub-processes\",\n    \"keywords\": [],\n    \"homepage\": \"https://symfony.com\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Fabien Potencier\",\n            \"email\": \"fabien@symfony.com\"\n        },\n        {\n            \"name\": \"Symfony Community\",\n            \"homepage\": \"https://symfony.com/contributors\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.2.5\",\n        \"symfony/polyfill-php80\": \"^1.16\"\n    },\n    \"autoload\": {\n        \"psr-4\": { \"Symfony\\\\Component\\\\Process\\\\\": \"\" },\n        \"exclude-from-classmap\": [\n            \"/Tests/\"\n        ]\n    },\n    \"minimum-stability\": \"dev\"\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/CHANGELOG.md",
    "content": "CHANGELOG\n=========\n\n5.4\n---\n\n * Add ability to style integer and double values independently\n * Add casters for Symfony's UUIDs and ULIDs\n * Add support for `Fiber`\n\n5.2.0\n-----\n\n * added support for PHPUnit `--colors` option\n * added `VAR_DUMPER_FORMAT=server` env var value support\n * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set\n\n5.1.0\n-----\n\n * added `RdKafka` support\n\n4.4.0\n-----\n\n * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()`\n   to configure casters & flags to use in tests\n * added `ImagineCaster` and infrastructure to dump images\n * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data\n * added `UuidCaster`\n * made all casters final\n * added support for the `NO_COLOR` env var (https://no-color.org/)\n\n4.3.0\n-----\n\n * added `DsCaster` to support dumping the contents of data structures from the Ds extension\n\n4.2.0\n-----\n\n * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli`\n\n4.1.0\n-----\n\n * added a `ServerDumper` to send serialized Data clones to a server\n * added a `ServerDumpCommand` and `DumpServer` to run a server collecting\n   and displaying dumps on a single place with multiple formats support\n * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support\n\n4.0.0\n-----\n\n * support for passing `\\ReflectionClass` instances to the `Caster::castObject()`\n   method has been dropped, pass class names as strings instead\n * the `Data::getRawData()` method has been removed\n * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0`\n   argument and moves `$message = ''` argument at 4th position.\n * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0`\n   argument and moves `$message = ''` argument at 4th position.\n\n3.4.0\n-----\n\n * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth\n * deprecated `MongoCaster`\n\n2.7.0\n-----\n\n * deprecated `Cloner\\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead.\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/AmqpCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Amqp related classes to array representation.\n *\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n *\n * @final\n */\nclass AmqpCaster\n{\n    private const FLAGS = [\n        \\AMQP_DURABLE => 'AMQP_DURABLE',\n        \\AMQP_PASSIVE => 'AMQP_PASSIVE',\n        \\AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE',\n        \\AMQP_AUTODELETE => 'AMQP_AUTODELETE',\n        \\AMQP_INTERNAL => 'AMQP_INTERNAL',\n        \\AMQP_NOLOCAL => 'AMQP_NOLOCAL',\n        \\AMQP_AUTOACK => 'AMQP_AUTOACK',\n        \\AMQP_IFEMPTY => 'AMQP_IFEMPTY',\n        \\AMQP_IFUNUSED => 'AMQP_IFUNUSED',\n        \\AMQP_MANDATORY => 'AMQP_MANDATORY',\n        \\AMQP_IMMEDIATE => 'AMQP_IMMEDIATE',\n        \\AMQP_MULTIPLE => 'AMQP_MULTIPLE',\n        \\AMQP_NOWAIT => 'AMQP_NOWAIT',\n        \\AMQP_REQUEUE => 'AMQP_REQUEUE',\n    ];\n\n    private const EXCHANGE_TYPES = [\n        \\AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT',\n        \\AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT',\n        \\AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC',\n        \\AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS',\n    ];\n\n    public static function castConnection(\\AMQPConnection $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'is_connected' => $c->isConnected(),\n        ];\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPConnection\\x00login\"])) {\n            return $a;\n        }\n\n        // BC layer in the amqp lib\n        if (method_exists($c, 'getReadTimeout')) {\n            $timeout = $c->getReadTimeout();\n        } else {\n            $timeout = $c->getTimeout();\n        }\n\n        $a += [\n            $prefix.'is_connected' => $c->isConnected(),\n            $prefix.'login' => $c->getLogin(),\n            $prefix.'password' => $c->getPassword(),\n            $prefix.'host' => $c->getHost(),\n            $prefix.'vhost' => $c->getVhost(),\n            $prefix.'port' => $c->getPort(),\n            $prefix.'read_timeout' => $timeout,\n        ];\n\n        return $a;\n    }\n\n    public static function castChannel(\\AMQPChannel $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'is_connected' => $c->isConnected(),\n            $prefix.'channel_id' => $c->getChannelId(),\n        ];\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPChannel\\x00connection\"])) {\n            return $a;\n        }\n\n        $a += [\n            $prefix.'connection' => $c->getConnection(),\n            $prefix.'prefetch_size' => $c->getPrefetchSize(),\n            $prefix.'prefetch_count' => $c->getPrefetchCount(),\n        ];\n\n        return $a;\n    }\n\n    public static function castQueue(\\AMQPQueue $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'flags' => self::extractFlags($c->getFlags()),\n        ];\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPQueue\\x00name\"])) {\n            return $a;\n        }\n\n        $a += [\n            $prefix.'connection' => $c->getConnection(),\n            $prefix.'channel' => $c->getChannel(),\n            $prefix.'name' => $c->getName(),\n            $prefix.'arguments' => $c->getArguments(),\n        ];\n\n        return $a;\n    }\n\n    public static function castExchange(\\AMQPExchange $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'flags' => self::extractFlags($c->getFlags()),\n        ];\n\n        $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType();\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPExchange\\x00name\"])) {\n            $a[\"\\x00AMQPExchange\\x00type\"] = $type;\n\n            return $a;\n        }\n\n        $a += [\n            $prefix.'connection' => $c->getConnection(),\n            $prefix.'channel' => $c->getChannel(),\n            $prefix.'name' => $c->getName(),\n            $prefix.'type' => $type,\n            $prefix.'arguments' => $c->getArguments(),\n        ];\n\n        return $a;\n    }\n\n    public static function castEnvelope(\\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode());\n\n        // Recent version of the extension already expose private properties\n        if (isset($a[\"\\x00AMQPEnvelope\\x00body\"])) {\n            $a[\"\\0AMQPEnvelope\\0delivery_mode\"] = $deliveryMode;\n\n            return $a;\n        }\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE)) {\n            $a += [$prefix.'body' => $c->getBody()];\n        }\n\n        $a += [\n            $prefix.'delivery_tag' => $c->getDeliveryTag(),\n            $prefix.'is_redelivery' => $c->isRedelivery(),\n            $prefix.'exchange_name' => $c->getExchangeName(),\n            $prefix.'routing_key' => $c->getRoutingKey(),\n            $prefix.'content_type' => $c->getContentType(),\n            $prefix.'content_encoding' => $c->getContentEncoding(),\n            $prefix.'headers' => $c->getHeaders(),\n            $prefix.'delivery_mode' => $deliveryMode,\n            $prefix.'priority' => $c->getPriority(),\n            $prefix.'correlation_id' => $c->getCorrelationId(),\n            $prefix.'reply_to' => $c->getReplyTo(),\n            $prefix.'expiration' => $c->getExpiration(),\n            $prefix.'message_id' => $c->getMessageId(),\n            $prefix.'timestamp' => $c->getTimeStamp(),\n            $prefix.'type' => $c->getType(),\n            $prefix.'user_id' => $c->getUserId(),\n            $prefix.'app_id' => $c->getAppId(),\n        ];\n\n        return $a;\n    }\n\n    private static function extractFlags(int $flags): ConstStub\n    {\n        $flagsArray = [];\n\n        foreach (self::FLAGS as $value => $name) {\n            if ($flags & $value) {\n                $flagsArray[] = $name;\n            }\n        }\n\n        if (!$flagsArray) {\n            $flagsArray = ['AMQP_NOPARAM'];\n        }\n\n        return new ConstStub(implode('|', $flagsArray), $flags);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ArgsStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a list of function arguments.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ArgsStub extends EnumStub\n{\n    private static $parameters = [];\n\n    public function __construct(array $args, string $function, ?string $class)\n    {\n        [$variadic, $params] = self::getParameters($function, $class);\n\n        $values = [];\n        foreach ($args as $k => $v) {\n            $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;\n        }\n        if (null === $params) {\n            parent::__construct($values, false);\n\n            return;\n        }\n        if (\\count($values) < \\count($params)) {\n            $params = \\array_slice($params, 0, \\count($values));\n        } elseif (\\count($values) > \\count($params)) {\n            $values[] = new EnumStub(array_splice($values, \\count($params)), false);\n            $params[] = $variadic;\n        }\n        if (['...'] === $params) {\n            $this->dumpKeys = false;\n            $this->value = $values[0]->value;\n        } else {\n            $this->value = array_combine($params, $values);\n        }\n    }\n\n    private static function getParameters(string $function, ?string $class): array\n    {\n        if (isset(self::$parameters[$k = $class.'::'.$function])) {\n            return self::$parameters[$k];\n        }\n\n        try {\n            $r = null !== $class ? new \\ReflectionMethod($class, $function) : new \\ReflectionFunction($function);\n        } catch (\\ReflectionException $e) {\n            return [null, null];\n        }\n\n        $variadic = '...';\n        $params = [];\n        foreach ($r->getParameters() as $v) {\n            $k = '$'.$v->name;\n            if ($v->isPassedByReference()) {\n                $k = '&'.$k;\n            }\n            if ($v->isVariadic()) {\n                $variadic .= $k;\n            } else {\n                $params[] = $k;\n            }\n        }\n\n        return self::$parameters[$k] = [$variadic, $params];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/Caster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Helper for filtering out properties in casters.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass Caster\n{\n    public const EXCLUDE_VERBOSE = 1;\n    public const EXCLUDE_VIRTUAL = 2;\n    public const EXCLUDE_DYNAMIC = 4;\n    public const EXCLUDE_PUBLIC = 8;\n    public const EXCLUDE_PROTECTED = 16;\n    public const EXCLUDE_PRIVATE = 32;\n    public const EXCLUDE_NULL = 64;\n    public const EXCLUDE_EMPTY = 128;\n    public const EXCLUDE_NOT_IMPORTANT = 256;\n    public const EXCLUDE_STRICT = 512;\n\n    public const PREFIX_VIRTUAL = \"\\0~\\0\";\n    public const PREFIX_DYNAMIC = \"\\0+\\0\";\n    public const PREFIX_PROTECTED = \"\\0*\\0\";\n\n    /**\n     * Casts objects to arrays and adds the dynamic property prefix.\n     *\n     * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not\n     */\n    public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array\n    {\n        if ($hasDebugInfo) {\n            try {\n                $debugInfo = $obj->__debugInfo();\n            } catch (\\Exception $e) {\n                // ignore failing __debugInfo()\n                $hasDebugInfo = false;\n            }\n        }\n\n        $a = $obj instanceof \\Closure ? [] : (array) $obj;\n\n        if ($obj instanceof \\__PHP_Incomplete_Class) {\n            return $a;\n        }\n\n        if ($a) {\n            static $publicProperties = [];\n            $debugClass = $debugClass ?? get_debug_type($obj);\n\n            $i = 0;\n            $prefixedKeys = [];\n            foreach ($a as $k => $v) {\n                if (\"\\0\" !== ($k[0] ?? '')) {\n                    if (!isset($publicProperties[$class])) {\n                        foreach ((new \\ReflectionClass($class))->getProperties(\\ReflectionProperty::IS_PUBLIC) as $prop) {\n                            $publicProperties[$class][$prop->name] = true;\n                        }\n                    }\n                    if (!isset($publicProperties[$class][$k])) {\n                        $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;\n                    }\n                } elseif ($debugClass !== $class && 1 === strpos($k, $class)) {\n                    $prefixedKeys[$i] = \"\\0\".$debugClass.strrchr($k, \"\\0\");\n                }\n                ++$i;\n            }\n            if ($prefixedKeys) {\n                $keys = array_keys($a);\n                foreach ($prefixedKeys as $i => $k) {\n                    $keys[$i] = $k;\n                }\n                $a = array_combine($keys, $a);\n            }\n        }\n\n        if ($hasDebugInfo && \\is_array($debugInfo)) {\n            foreach ($debugInfo as $k => $v) {\n                if (!isset($k[0]) || \"\\0\" !== $k[0]) {\n                    if (\\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) {\n                        continue;\n                    }\n                    $k = self::PREFIX_VIRTUAL.$k;\n                }\n\n                unset($a[$k]);\n                $a[$k] = $v;\n            }\n        }\n\n        return $a;\n    }\n\n    /**\n     * Filters out the specified properties.\n     *\n     * By default, a single match in the $filter bit field filters properties out, following an \"or\" logic.\n     * When EXCLUDE_STRICT is set, an \"and\" logic is applied: all bits must match for a property to be removed.\n     *\n     * @param array    $a                The array containing the properties to filter\n     * @param int      $filter           A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out\n     * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set\n     * @param int      &$count           Set to the number of removed properties\n     */\n    public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array\n    {\n        $count = 0;\n\n        foreach ($a as $k => $v) {\n            $type = self::EXCLUDE_STRICT & $filter;\n\n            if (null === $v) {\n                $type |= self::EXCLUDE_NULL & $filter;\n                $type |= self::EXCLUDE_EMPTY & $filter;\n            } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) {\n                $type |= self::EXCLUDE_EMPTY & $filter;\n            }\n            if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\\in_array($k, $listedProperties, true)) {\n                $type |= self::EXCLUDE_NOT_IMPORTANT;\n            }\n            if ((self::EXCLUDE_VERBOSE & $filter) && \\in_array($k, $listedProperties, true)) {\n                $type |= self::EXCLUDE_VERBOSE;\n            }\n\n            if (!isset($k[1]) || \"\\0\" !== $k[0]) {\n                $type |= self::EXCLUDE_PUBLIC & $filter;\n            } elseif ('~' === $k[1]) {\n                $type |= self::EXCLUDE_VIRTUAL & $filter;\n            } elseif ('+' === $k[1]) {\n                $type |= self::EXCLUDE_DYNAMIC & $filter;\n            } elseif ('*' === $k[1]) {\n                $type |= self::EXCLUDE_PROTECTED & $filter;\n            } else {\n                $type |= self::EXCLUDE_PRIVATE & $filter;\n            }\n\n            if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {\n                unset($a[$k]);\n                ++$count;\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castPhpIncompleteClass(\\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if (isset($a['__PHP_Incomplete_Class_Name'])) {\n            $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')';\n            unset($a['__PHP_Incomplete_Class_Name']);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ClassStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a PHP class identifier.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ClassStub extends ConstStub\n{\n    /**\n     * @param string   $identifier A PHP identifier, e.g. a class, method, interface, etc. name\n     * @param callable $callable   The callable targeted by the identifier when it is ambiguous or not a real PHP identifier\n     */\n    public function __construct(string $identifier, $callable = null)\n    {\n        $this->value = $identifier;\n\n        try {\n            if (null !== $callable) {\n                if ($callable instanceof \\Closure) {\n                    $r = new \\ReflectionFunction($callable);\n                } elseif (\\is_object($callable)) {\n                    $r = [$callable, '__invoke'];\n                } elseif (\\is_array($callable)) {\n                    $r = $callable;\n                } elseif (false !== $i = strpos($callable, '::')) {\n                    $r = [substr($callable, 0, $i), substr($callable, 2 + $i)];\n                } else {\n                    $r = new \\ReflectionFunction($callable);\n                }\n            } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) {\n                $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)];\n            } else {\n                $r = new \\ReflectionClass($identifier);\n            }\n\n            if (\\is_array($r)) {\n                try {\n                    $r = new \\ReflectionMethod($r[0], $r[1]);\n                } catch (\\ReflectionException $e) {\n                    $r = new \\ReflectionClass($r[0]);\n                }\n            }\n\n            if (str_contains($identifier, \"@anonymous\\0\")) {\n                $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\\x7f-\\xff][\\\\\\\\a-zA-Z0-9_\\x7f-\\xff]*+@anonymous\\x00.*?\\.php(?:0x?|:[0-9]++\\$)[0-9a-fA-F]++/', function ($m) {\n                    return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];\n                }, $identifier);\n            }\n\n            if (null !== $callable && $r instanceof \\ReflectionFunctionAbstract) {\n                $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE);\n                $s = ReflectionCaster::getSignature($s);\n\n                if (str_ends_with($identifier, '()')) {\n                    $this->value = substr_replace($identifier, $s, -2);\n                } else {\n                    $this->value .= $s;\n                }\n            }\n        } catch (\\ReflectionException $e) {\n            return;\n        } finally {\n            if (0 < $i = strrpos($this->value, '\\\\')) {\n                $this->attr['ellipsis'] = \\strlen($this->value) - $i;\n                $this->attr['ellipsis-type'] = 'class';\n                $this->attr['ellipsis-tail'] = 1;\n            }\n        }\n\n        if ($f = $r->getFileName()) {\n            $this->attr['file'] = $f;\n            $this->attr['line'] = $r->getStartLine();\n        }\n    }\n\n    public static function wrapCallable($callable)\n    {\n        if (\\is_object($callable) || !\\is_callable($callable)) {\n            return $callable;\n        }\n\n        if (!\\is_array($callable)) {\n            $callable = new static($callable, $callable);\n        } elseif (\\is_string($callable[0])) {\n            $callable[0] = new static($callable[0], $callable);\n        } else {\n            $callable[1] = new static($callable[1], $callable);\n        }\n\n        return $callable;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ConstStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a PHP constant and its value.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ConstStub extends Stub\n{\n    public function __construct(string $name, $value = null)\n    {\n        $this->class = $name;\n        $this->value = 1 < \\func_num_args() ? $value : $name;\n    }\n\n    /**\n     * @return string\n     */\n    public function __toString()\n    {\n        return (string) $this->value;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/CutArrayStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents a cut array.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CutArrayStub extends CutStub\n{\n    public $preservedSubset;\n\n    public function __construct(array $value, array $preservedKeys)\n    {\n        parent::__construct($value);\n\n        $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys));\n        $this->cut -= \\count($this->preservedSubset);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/CutStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents the main properties of a PHP variable, pre-casted by a caster.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CutStub extends Stub\n{\n    public function __construct($value)\n    {\n        $this->value = $value;\n\n        switch (\\gettype($value)) {\n            case 'object':\n                $this->type = self::TYPE_OBJECT;\n                $this->class = \\get_class($value);\n\n                if ($value instanceof \\Closure) {\n                    ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE);\n                }\n\n                $this->cut = -1;\n                break;\n\n            case 'array':\n                $this->type = self::TYPE_ARRAY;\n                $this->class = self::ARRAY_ASSOC;\n                $this->cut = $this->value = \\count($value);\n                break;\n\n            case 'resource':\n            case 'unknown type':\n            case 'resource (closed)':\n                $this->type = self::TYPE_RESOURCE;\n                $this->handle = (int) $value;\n                if ('Unknown' === $this->class = @get_resource_type($value)) {\n                    $this->class = 'Closed';\n                }\n                $this->cut = -1;\n                break;\n\n            case 'string':\n                $this->type = self::TYPE_STRING;\n                $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;\n                $this->cut = self::STRING_BINARY === $this->class ? \\strlen($value) : mb_strlen($value, 'UTF-8');\n                $this->value = '';\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/DOMCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts DOM related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass DOMCaster\n{\n    private const ERROR_CODES = [\n        \\DOM_PHP_ERR => 'DOM_PHP_ERR',\n        \\DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR',\n        \\DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR',\n        \\DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR',\n        \\DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR',\n        \\DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR',\n        \\DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR',\n        \\DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR',\n        \\DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR',\n        \\DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR',\n        \\DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR',\n        \\DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR',\n        \\DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR',\n        \\DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR',\n        \\DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR',\n        \\DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR',\n        \\DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR',\n    ];\n\n    private const NODE_TYPES = [\n        \\XML_ELEMENT_NODE => 'XML_ELEMENT_NODE',\n        \\XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE',\n        \\XML_TEXT_NODE => 'XML_TEXT_NODE',\n        \\XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE',\n        \\XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE',\n        \\XML_ENTITY_NODE => 'XML_ENTITY_NODE',\n        \\XML_PI_NODE => 'XML_PI_NODE',\n        \\XML_COMMENT_NODE => 'XML_COMMENT_NODE',\n        \\XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE',\n        \\XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE',\n        \\XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE',\n        \\XML_NOTATION_NODE => 'XML_NOTATION_NODE',\n        \\XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE',\n        \\XML_DTD_NODE => 'XML_DTD_NODE',\n        \\XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE',\n        \\XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE',\n        \\XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE',\n        \\XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE',\n    ];\n\n    public static function castException(\\DOMException $e, array $a, Stub $stub, bool $isNested)\n    {\n        $k = Caster::PREFIX_PROTECTED.'code';\n        if (isset($a[$k], self::ERROR_CODES[$a[$k]])) {\n            $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]);\n        }\n\n        return $a;\n    }\n\n    public static function castLength($dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'length' => $dom->length,\n        ];\n\n        return $a;\n    }\n\n    public static function castImplementation(\\DOMImplementation $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'Core' => '1.0',\n            Caster::PREFIX_VIRTUAL.'XML' => '2.0',\n        ];\n\n        return $a;\n    }\n\n    public static function castNode(\\DOMNode $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'nodeName' => $dom->nodeName,\n            'nodeValue' => new CutStub($dom->nodeValue),\n            'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType),\n            'parentNode' => new CutStub($dom->parentNode),\n            'childNodes' => $dom->childNodes,\n            'firstChild' => new CutStub($dom->firstChild),\n            'lastChild' => new CutStub($dom->lastChild),\n            'previousSibling' => new CutStub($dom->previousSibling),\n            'nextSibling' => new CutStub($dom->nextSibling),\n            'attributes' => $dom->attributes,\n            'ownerDocument' => new CutStub($dom->ownerDocument),\n            'namespaceURI' => $dom->namespaceURI,\n            'prefix' => $dom->prefix,\n            'localName' => $dom->localName,\n            'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI,\n            'textContent' => new CutStub($dom->textContent),\n        ];\n\n        return $a;\n    }\n\n    public static function castNameSpaceNode(\\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'nodeName' => $dom->nodeName,\n            'nodeValue' => new CutStub($dom->nodeValue),\n            'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType),\n            'prefix' => $dom->prefix,\n            'localName' => $dom->localName,\n            'namespaceURI' => $dom->namespaceURI,\n            'ownerDocument' => new CutStub($dom->ownerDocument),\n            'parentNode' => new CutStub($dom->parentNode),\n        ];\n\n        return $a;\n    }\n\n    public static function castDocument(\\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $a += [\n            'doctype' => $dom->doctype,\n            'implementation' => $dom->implementation,\n            'documentElement' => new CutStub($dom->documentElement),\n            'actualEncoding' => $dom->actualEncoding,\n            'encoding' => $dom->encoding,\n            'xmlEncoding' => $dom->xmlEncoding,\n            'standalone' => $dom->standalone,\n            'xmlStandalone' => $dom->xmlStandalone,\n            'version' => $dom->version,\n            'xmlVersion' => $dom->xmlVersion,\n            'strictErrorChecking' => $dom->strictErrorChecking,\n            'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI,\n            'config' => $dom->config,\n            'formatOutput' => $dom->formatOutput,\n            'validateOnParse' => $dom->validateOnParse,\n            'resolveExternals' => $dom->resolveExternals,\n            'preserveWhiteSpace' => $dom->preserveWhiteSpace,\n            'recover' => $dom->recover,\n            'substituteEntities' => $dom->substituteEntities,\n        ];\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE)) {\n            $formatOutput = $dom->formatOutput;\n            $dom->formatOutput = true;\n            $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()];\n            $dom->formatOutput = $formatOutput;\n        }\n\n        return $a;\n    }\n\n    public static function castCharacterData(\\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'data' => $dom->data,\n            'length' => $dom->length,\n        ];\n\n        return $a;\n    }\n\n    public static function castAttr(\\DOMAttr $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'name' => $dom->name,\n            'specified' => $dom->specified,\n            'value' => $dom->value,\n            'ownerElement' => $dom->ownerElement,\n            'schemaTypeInfo' => $dom->schemaTypeInfo,\n        ];\n\n        return $a;\n    }\n\n    public static function castElement(\\DOMElement $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'tagName' => $dom->tagName,\n            'schemaTypeInfo' => $dom->schemaTypeInfo,\n        ];\n\n        return $a;\n    }\n\n    public static function castText(\\DOMText $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'wholeText' => $dom->wholeText,\n        ];\n\n        return $a;\n    }\n\n    public static function castTypeinfo(\\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'typeName' => $dom->typeName,\n            'typeNamespace' => $dom->typeNamespace,\n        ];\n\n        return $a;\n    }\n\n    public static function castDomError(\\DOMDomError $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'severity' => $dom->severity,\n            'message' => $dom->message,\n            'type' => $dom->type,\n            'relatedException' => $dom->relatedException,\n            'related_data' => $dom->related_data,\n            'location' => $dom->location,\n        ];\n\n        return $a;\n    }\n\n    public static function castLocator(\\DOMLocator $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'lineNumber' => $dom->lineNumber,\n            'columnNumber' => $dom->columnNumber,\n            'offset' => $dom->offset,\n            'relatedNode' => $dom->relatedNode,\n            'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri,\n        ];\n\n        return $a;\n    }\n\n    public static function castDocumentType(\\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'name' => $dom->name,\n            'entities' => $dom->entities,\n            'notations' => $dom->notations,\n            'publicId' => $dom->publicId,\n            'systemId' => $dom->systemId,\n            'internalSubset' => $dom->internalSubset,\n        ];\n\n        return $a;\n    }\n\n    public static function castNotation(\\DOMNotation $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'publicId' => $dom->publicId,\n            'systemId' => $dom->systemId,\n        ];\n\n        return $a;\n    }\n\n    public static function castEntity(\\DOMEntity $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'publicId' => $dom->publicId,\n            'systemId' => $dom->systemId,\n            'notationName' => $dom->notationName,\n            'actualEncoding' => $dom->actualEncoding,\n            'encoding' => $dom->encoding,\n            'version' => $dom->version,\n        ];\n\n        return $a;\n    }\n\n    public static function castProcessingInstruction(\\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'target' => $dom->target,\n            'data' => $dom->data,\n        ];\n\n        return $a;\n    }\n\n    public static function castXPath(\\DOMXPath $dom, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            'document' => $dom->document,\n        ];\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/DateCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts DateTimeInterface related classes to array representation.\n *\n * @author Dany Maillard <danymaillard93b@gmail.com>\n *\n * @final\n */\nclass DateCaster\n{\n    private const PERIOD_LIMIT = 3;\n\n    public static function castDateTime(\\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $location = $d->getTimezone()->getLocation();\n        $fromNow = (new \\DateTime())->diff($d);\n\n        $title = $d->format('l, F j, Y')\n            .\"\\n\".self::formatInterval($fromNow).' from now'\n            .($location ? ($d->format('I') ? \"\\nDST On\" : \"\\nDST Off\") : '')\n        ;\n\n        unset(\n            $a[Caster::PREFIX_DYNAMIC.'date'],\n            $a[Caster::PREFIX_DYNAMIC.'timezone'],\n            $a[Caster::PREFIX_DYNAMIC.'timezone_type']\n        );\n        $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title);\n\n        $stub->class .= $d->format(' @U');\n\n        return $a;\n    }\n\n    public static function castInterval(\\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter)\n    {\n        $now = new \\DateTimeImmutable('@0', new \\DateTimeZone('UTC'));\n        $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp();\n        $title = number_format($numberOfSeconds, 0, '.', ' ').'s';\n\n        $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)];\n\n        return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a;\n    }\n\n    private static function formatInterval(\\DateInterval $i): string\n    {\n        $format = '%R ';\n\n        if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) {\n            $d = new \\DateTimeImmutable('@0', new \\DateTimeZone('UTC'));\n            $i = $d->diff($d->add($i)); // recalculate carry over points\n            $format .= 0 < $i->days ? '%ad ' : '';\n        } else {\n            $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : '');\n        }\n\n        $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : '';\n        $format = '%R ' === $format ? '0s' : $format;\n\n        return $i->format(rtrim($format));\n    }\n\n    public static function castTimeZone(\\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter)\n    {\n        $location = $timeZone->getLocation();\n        $formatted = (new \\DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P');\n        $title = $location && \\extension_loaded('intl') ? \\Locale::getDisplayRegion('-'.$location['country_code']) : '';\n\n        $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)];\n\n        return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a;\n    }\n\n    public static function castPeriod(\\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter)\n    {\n        $dates = [];\n        foreach (clone $p as $i => $d) {\n            if (self::PERIOD_LIMIT === $i) {\n                $now = new \\DateTimeImmutable('now', new \\DateTimeZone('UTC'));\n                $dates[] = sprintf('%s more', ($end = $p->getEndDate())\n                    ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u')))\n                    : $p->recurrences - $i\n                );\n                break;\n            }\n            $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d));\n        }\n\n        $period = sprintf(\n            'every %s, from %s (%s) %s',\n            self::formatInterval($p->getDateInterval()),\n            self::formatDateTime($p->getStartDate()),\n            $p->include_start_date ? 'included' : 'excluded',\n            ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end) : 'recurring '.$p->recurrences.' time/s'\n        );\n\n        $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode(\"\\n\", $dates))];\n\n        return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a;\n    }\n\n    private static function formatDateTime(\\DateTimeInterface $d, string $extra = ''): string\n    {\n        return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra);\n    }\n\n    private static function formatSeconds(string $s, string $us): string\n    {\n        return sprintf('%02d.%s', $s, 0 === ($len = \\strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us));\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/DoctrineCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Doctrine\\Common\\Proxy\\Proxy as CommonProxy;\nuse Doctrine\\ORM\\PersistentCollection;\nuse Doctrine\\ORM\\Proxy\\Proxy as OrmProxy;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Doctrine related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass DoctrineCaster\n{\n    public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested)\n    {\n        foreach (['__cloner__', '__initializer__'] as $k) {\n            if (\\array_key_exists($k, $a)) {\n                unset($a[$k]);\n                ++$stub->cut;\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested)\n    {\n        foreach (['_entityPersister', '_identifier'] as $k) {\n            if (\\array_key_exists($k = \"\\0Doctrine\\\\ORM\\\\Proxy\\\\Proxy\\0\".$k, $a)) {\n                unset($a[$k]);\n                ++$stub->cut;\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested)\n    {\n        foreach (['snapshot', 'association', 'typeClass'] as $k) {\n            if (\\array_key_exists($k = \"\\0Doctrine\\\\ORM\\\\PersistentCollection\\0\".$k, $a)) {\n                $a[$k] = new CutStub($a[$k]);\n            }\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/DsCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Ds\\Collection;\nuse Ds\\Map;\nuse Ds\\Pair;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Ds extension classes to array representation.\n *\n * @author Jáchym Toušek <enumag@gmail.com>\n *\n * @final\n */\nclass DsCaster\n{\n    public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count();\n        $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity();\n\n        if (!$c instanceof Map) {\n            $a += $c->toArray();\n        }\n\n        return $a;\n    }\n\n    public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach ($c as $k => $v) {\n            $a[] = new DsPairStub($k, $v);\n        }\n\n        return $a;\n    }\n\n    public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach ($c->toArray() as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n        }\n\n        return $a;\n    }\n\n    public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array\n    {\n        if ($isNested) {\n            $stub->class = Pair::class;\n            $stub->value = null;\n            $stub->handle = 0;\n\n            $a = $c->value;\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/DsPairStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass DsPairStub extends Stub\n{\n    public function __construct($key, $value)\n    {\n        $this->value = [\n            Caster::PREFIX_VIRTUAL.'key' => $key,\n            Caster::PREFIX_VIRTUAL.'value' => $value,\n        ];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/EnumStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents an enumeration of values.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass EnumStub extends Stub\n{\n    public $dumpKeys = true;\n\n    public function __construct(array $values, bool $dumpKeys = true)\n    {\n        $this->value = $values;\n        $this->dumpKeys = $dumpKeys;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ExceptionCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\nuse Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException;\n\n/**\n * Casts common Exception classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass ExceptionCaster\n{\n    public static $srcContext = 1;\n    public static $traceArgs = true;\n    public static $errorTypes = [\n        \\E_DEPRECATED => 'E_DEPRECATED',\n        \\E_USER_DEPRECATED => 'E_USER_DEPRECATED',\n        \\E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',\n        \\E_ERROR => 'E_ERROR',\n        \\E_WARNING => 'E_WARNING',\n        \\E_PARSE => 'E_PARSE',\n        \\E_NOTICE => 'E_NOTICE',\n        \\E_CORE_ERROR => 'E_CORE_ERROR',\n        \\E_CORE_WARNING => 'E_CORE_WARNING',\n        \\E_COMPILE_ERROR => 'E_COMPILE_ERROR',\n        \\E_COMPILE_WARNING => 'E_COMPILE_WARNING',\n        \\E_USER_ERROR => 'E_USER_ERROR',\n        \\E_USER_WARNING => 'E_USER_WARNING',\n        \\E_USER_NOTICE => 'E_USER_NOTICE',\n        \\E_STRICT => 'E_STRICT',\n    ];\n\n    private static $framesCache = [];\n\n    public static function castError(\\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        return self::filterExceptionArray($stub->class, $a, \"\\0Error\\0\", $filter);\n    }\n\n    public static function castException(\\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        return self::filterExceptionArray($stub->class, $a, \"\\0Exception\\0\", $filter);\n    }\n\n    public static function castErrorException(\\ErrorException $e, array $a, Stub $stub, bool $isNested)\n    {\n        if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) {\n            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);\n        }\n\n        return $a;\n    }\n\n    public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested)\n    {\n        $trace = Caster::PREFIX_VIRTUAL.'trace';\n        $prefix = Caster::PREFIX_PROTECTED;\n        $xPrefix = \"\\0Exception\\0\";\n\n        if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \\Exception) {\n            $b = (array) $a[$xPrefix.'previous'];\n            $class = get_debug_type($a[$xPrefix.'previous']);\n            self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']);\n            $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\\count($a[$trace]->value));\n        }\n\n        unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']);\n\n        return $a;\n    }\n\n    public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested)\n    {\n        $sPrefix = \"\\0\".SilencedErrorContext::class.\"\\0\";\n\n        if (!isset($a[$s = $sPrefix.'severity'])) {\n            return $a;\n        }\n\n        if (isset(self::$errorTypes[$a[$s]])) {\n            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);\n        }\n\n        $trace = [[\n            'file' => $a[$sPrefix.'file'],\n            'line' => $a[$sPrefix.'line'],\n        ]];\n\n        if (isset($a[$sPrefix.'trace'])) {\n            $trace = array_merge($trace, $a[$sPrefix.'trace']);\n        }\n\n        unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']);\n        $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);\n\n        return $a;\n    }\n\n    public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested)\n    {\n        if (!$isNested) {\n            return $a;\n        }\n        $stub->class = '';\n        $stub->handle = 0;\n        $frames = $trace->value;\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a = [];\n        $j = \\count($frames);\n        if (0 > $i = $trace->sliceOffset) {\n            $i = max(0, $j + $i);\n        }\n        if (!isset($trace->value[$i])) {\n            return [];\n        }\n        $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';\n        $frames[] = ['function' => ''];\n        $collapse = false;\n\n        for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {\n            $f = $frames[$i];\n            $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???';\n\n            $frame = new FrameStub(\n                [\n                    'object' => $f['object'] ?? null,\n                    'class' => $f['class'] ?? null,\n                    'type' => $f['type'] ?? null,\n                    'function' => $f['function'] ?? null,\n                ] + $frames[$i - 1],\n                false,\n                true\n            );\n            $f = self::castFrameStub($frame, [], $frame, true);\n            if (isset($f[$prefix.'src'])) {\n                foreach ($f[$prefix.'src']->value as $label => $frame) {\n                    if (str_starts_with($label, \"\\0~collapse=0\")) {\n                        if ($collapse) {\n                            $label = substr_replace($label, '1', 11, 1);\n                        } else {\n                            $collapse = true;\n                        }\n                    }\n                    $label = substr_replace($label, \"title=Stack level $j.&\", 2, 0);\n                }\n                $f = $frames[$i - 1];\n                if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) {\n                    $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null);\n                }\n            } elseif ('???' !== $lastCall) {\n                $label = new ClassStub($lastCall);\n                if (isset($label->attr['ellipsis'])) {\n                    $label->attr['ellipsis'] += 2;\n                    $label = substr_replace($prefix, \"ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.\", 2, 0).$label->value.'()';\n                } else {\n                    $label = substr_replace($prefix, \"title=Stack level $j.\", 2, 0).$label->value.'()';\n                }\n            } else {\n                $label = substr_replace($prefix, \"title=Stack level $j.\", 2, 0).$lastCall;\n            }\n            $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame;\n\n            $lastCall = $call;\n        }\n        if (null !== $trace->sliceLength) {\n            $a = \\array_slice($a, 0, $trace->sliceLength, true);\n        }\n\n        return $a;\n    }\n\n    public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested)\n    {\n        if (!$isNested) {\n            return $a;\n        }\n        $f = $frame->value;\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if (isset($f['file'], $f['line'])) {\n            $cacheKey = $f;\n            unset($cacheKey['object'], $cacheKey['args']);\n            $cacheKey[] = self::$srcContext;\n            $cacheKey = implode('-', $cacheKey);\n\n            if (isset(self::$framesCache[$cacheKey])) {\n                $a[$prefix.'src'] = self::$framesCache[$cacheKey];\n            } else {\n                if (preg_match('/\\((\\d+)\\)(?:\\([\\da-f]{32}\\))? : (?:eval\\(\\)\\'d code|runtime-created function)$/', $f['file'], $match)) {\n                    $f['file'] = substr($f['file'], 0, -\\strlen($match[0]));\n                    $f['line'] = (int) $match[1];\n                }\n                $src = $f['line'];\n                $srcKey = $f['file'];\n                $ellipsis = new LinkStub($srcKey, 0);\n                $srcAttr = 'collapse='.(int) $ellipsis->inVendor;\n                $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0;\n                $ellipsis = $ellipsis->attr['ellipsis'] ?? 0;\n\n                if (is_file($f['file']) && 0 <= self::$srcContext) {\n                    if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {\n                        $template = null;\n                        if (isset($f['object'])) {\n                            $template = $f['object'];\n                        } elseif ((new \\ReflectionClass($f['class']))->isInstantiable()) {\n                            $template = unserialize(sprintf('O:%d:\"%s\":0:{}', \\strlen($f['class']), $f['class']));\n                        }\n                        if (null !== $template) {\n                            $ellipsis = 0;\n                            $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');\n                            $templateInfo = $template->getDebugInfo();\n                            if (isset($templateInfo[$f['line']])) {\n                                if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) {\n                                    $templatePath = null;\n                                }\n                                if ($templateSrc) {\n                                    $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);\n                                    $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];\n                                }\n                            }\n                        }\n                    }\n                    if ($srcKey == $f['file']) {\n                        $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f);\n                        $srcKey .= ':'.$f['line'];\n                        if ($ellipsis) {\n                            $ellipsis += 1 + \\strlen($f['line']);\n                        }\n                    }\n                    $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']);\n                } else {\n                    $srcAttr .= '&separator=:';\n                }\n                $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : '';\n                self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub([\"\\0~$srcAttr\\0$srcKey\" => $src]);\n            }\n        }\n\n        unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']);\n        if ($frame->inTraceStub) {\n            unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']);\n        }\n        foreach ($a as $k => $v) {\n            if (!$v) {\n                unset($a[$k]);\n            }\n        }\n        if ($frame->keepArgs && !empty($f['args'])) {\n            $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']);\n        }\n\n        return $a;\n    }\n\n    private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array\n    {\n        if (isset($a[$xPrefix.'trace'])) {\n            $trace = $a[$xPrefix.'trace'];\n            unset($a[$xPrefix.'trace']); // Ensures the trace is always last\n        } else {\n            $trace = [];\n        }\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) {\n            if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {\n                self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);\n            }\n            $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);\n        }\n        if (empty($a[$xPrefix.'previous'])) {\n            unset($a[$xPrefix.'previous']);\n        }\n        unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']);\n\n        if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], \"@anonymous\\0\")) {\n            $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\\x7f-\\xff][\\\\\\\\a-zA-Z0-9_\\x7f-\\xff]*+@anonymous\\x00.*?\\.php(?:0x?|:[0-9]++\\$)[0-9a-fA-F]++/', function ($m) {\n                return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];\n            }, $a[Caster::PREFIX_PROTECTED.'message']);\n        }\n\n        if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {\n            $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);\n        }\n\n        return $a;\n    }\n\n    private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void\n    {\n        if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) {\n            return;\n        }\n        array_unshift($trace, [\n            'function' => $class ? 'new '.$class : null,\n            'file' => $file,\n            'line' => $line,\n        ]);\n    }\n\n    private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub\n    {\n        $srcLines = explode(\"\\n\", $srcLines);\n        $src = [];\n\n        for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {\n            $src[] = ($srcLines[$i] ?? '').\"\\n\";\n        }\n\n        if ($frame['function'] ?? false) {\n            $stub = new CutStub(new \\stdClass());\n            $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function'];\n            $stub->type = Stub::TYPE_OBJECT;\n            $stub->attr['cut_hash'] = true;\n            $stub->attr['file'] = $frame['file'];\n            $stub->attr['line'] = $frame['line'];\n\n            try {\n                $caller = isset($frame['class']) ? new \\ReflectionMethod($frame['class'], $frame['function']) : new \\ReflectionFunction($frame['function']);\n                $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE));\n\n                if ($f = $caller->getFileName()) {\n                    $stub->attr['file'] = $f;\n                    $stub->attr['line'] = $caller->getStartLine();\n                }\n            } catch (\\ReflectionException $e) {\n                // ignore fake class/function\n            }\n\n            $srcLines = [\"\\0~separator=\\0\" => $stub];\n        } else {\n            $stub = null;\n            $srcLines = [];\n        }\n\n        $ltrim = 0;\n        do {\n            $pad = null;\n            for ($i = $srcContext << 1; $i >= 0; --$i) {\n                if (isset($src[$i][$ltrim]) && \"\\r\" !== ($c = $src[$i][$ltrim]) && \"\\n\" !== $c) {\n                    if (null === $pad) {\n                        $pad = $c;\n                    }\n                    if ((' ' !== $c && \"\\t\" !== $c) || $pad !== $c) {\n                        break;\n                    }\n                }\n            }\n            ++$ltrim;\n        } while (0 > $i && null !== $pad);\n\n        --$ltrim;\n\n        foreach ($src as $i => $c) {\n            if ($ltrim) {\n                $c = isset($c[$ltrim]) && \"\\r\" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, \" \\t\");\n            }\n            $c = substr($c, 0, -1);\n            if ($i !== $srcContext) {\n                $c = new ConstStub('default', $c);\n            } else {\n                $c = new ConstStub($c, $stub ? 'in '.$stub->class : '');\n                if (null !== $file) {\n                    $c->attr['file'] = $file;\n                    $c->attr['line'] = $line;\n                }\n            }\n            $c->attr['lang'] = $lang;\n            $srcLines[sprintf(\"\\0~separator=› &%d\\0\", $i + $line - $srcContext)] = $c;\n        }\n\n        return new EnumStub($srcLines);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/FiberCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Fiber related classes to array representation.\n *\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nfinal class FiberCaster\n{\n    public static function castFiber(\\Fiber $fiber, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($fiber->isTerminated()) {\n            $status = 'terminated';\n        } elseif ($fiber->isRunning()) {\n            $status = 'running';\n        } elseif ($fiber->isSuspended()) {\n            $status = 'suspended';\n        } elseif ($fiber->isStarted()) {\n            $status = 'started';\n        } else {\n            $status = 'not started';\n        }\n\n        $a[$prefix.'status'] = $status;\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/FrameStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace().\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass FrameStub extends EnumStub\n{\n    public $keepArgs;\n    public $inTraceStub;\n\n    public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false)\n    {\n        $this->value = $frame;\n        $this->keepArgs = $keepArgs;\n        $this->inTraceStub = $inTraceStub;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/GmpCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts GMP objects to array representation.\n *\n * @author Hamza Amrouche <hamza.simperfit@gmail.com>\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass GmpCaster\n{\n    public static function castGmp(\\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array\n    {\n        $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp));\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ImagineCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Imagine\\Image\\ImageInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nfinal class ImagineCaster\n{\n    public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $imgData = $c->get('png');\n        if (\\strlen($imgData) > 1 * 1000 * 1000) {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()),\n            ];\n        } else {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()),\n            ];\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ImgStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nclass ImgStub extends ConstStub\n{\n    public function __construct(string $data, string $contentType, string $size = '')\n    {\n        $this->value = '';\n        $this->attr['img-data'] = $data;\n        $this->attr['img-size'] = $size;\n        $this->attr['content-type'] = $contentType;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/IntlCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>\n *\n * @final\n */\nclass IntlCaster\n{\n    public static function castMessageFormatter(\\MessageFormatter $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),\n            Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    public static function castNumberFormatter(\\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),\n            Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),\n        ];\n\n        if ($filter & Caster::EXCLUDE_VERBOSE) {\n            $stub->cut += 3;\n\n            return self::castError($c, $a);\n        }\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub(\n                [\n                    'PARSE_INT_ONLY' => $c->getAttribute(\\NumberFormatter::PARSE_INT_ONLY),\n                    'GROUPING_USED' => $c->getAttribute(\\NumberFormatter::GROUPING_USED),\n                    'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\\NumberFormatter::DECIMAL_ALWAYS_SHOWN),\n                    'MAX_INTEGER_DIGITS' => $c->getAttribute(\\NumberFormatter::MAX_INTEGER_DIGITS),\n                    'MIN_INTEGER_DIGITS' => $c->getAttribute(\\NumberFormatter::MIN_INTEGER_DIGITS),\n                    'INTEGER_DIGITS' => $c->getAttribute(\\NumberFormatter::INTEGER_DIGITS),\n                    'MAX_FRACTION_DIGITS' => $c->getAttribute(\\NumberFormatter::MAX_FRACTION_DIGITS),\n                    'MIN_FRACTION_DIGITS' => $c->getAttribute(\\NumberFormatter::MIN_FRACTION_DIGITS),\n                    'FRACTION_DIGITS' => $c->getAttribute(\\NumberFormatter::FRACTION_DIGITS),\n                    'MULTIPLIER' => $c->getAttribute(\\NumberFormatter::MULTIPLIER),\n                    'GROUPING_SIZE' => $c->getAttribute(\\NumberFormatter::GROUPING_SIZE),\n                    'ROUNDING_MODE' => $c->getAttribute(\\NumberFormatter::ROUNDING_MODE),\n                    'ROUNDING_INCREMENT' => $c->getAttribute(\\NumberFormatter::ROUNDING_INCREMENT),\n                    'FORMAT_WIDTH' => $c->getAttribute(\\NumberFormatter::FORMAT_WIDTH),\n                    'PADDING_POSITION' => $c->getAttribute(\\NumberFormatter::PADDING_POSITION),\n                    'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\\NumberFormatter::SECONDARY_GROUPING_SIZE),\n                    'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\\NumberFormatter::SIGNIFICANT_DIGITS_USED),\n                    'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\\NumberFormatter::MIN_SIGNIFICANT_DIGITS),\n                    'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\\NumberFormatter::MAX_SIGNIFICANT_DIGITS),\n                    'LENIENT_PARSE' => $c->getAttribute(\\NumberFormatter::LENIENT_PARSE),\n                ]\n            ),\n            Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub(\n                [\n                    'POSITIVE_PREFIX' => $c->getTextAttribute(\\NumberFormatter::POSITIVE_PREFIX),\n                    'POSITIVE_SUFFIX' => $c->getTextAttribute(\\NumberFormatter::POSITIVE_SUFFIX),\n                    'NEGATIVE_PREFIX' => $c->getTextAttribute(\\NumberFormatter::NEGATIVE_PREFIX),\n                    'NEGATIVE_SUFFIX' => $c->getTextAttribute(\\NumberFormatter::NEGATIVE_SUFFIX),\n                    'PADDING_CHARACTER' => $c->getTextAttribute(\\NumberFormatter::PADDING_CHARACTER),\n                    'CURRENCY_CODE' => $c->getTextAttribute(\\NumberFormatter::CURRENCY_CODE),\n                    'DEFAULT_RULESET' => $c->getTextAttribute(\\NumberFormatter::DEFAULT_RULESET),\n                    'PUBLIC_RULESETS' => $c->getTextAttribute(\\NumberFormatter::PUBLIC_RULESETS),\n                ]\n            ),\n            Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub(\n                [\n                    'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL),\n                    'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::GROUPING_SEPARATOR_SYMBOL),\n                    'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::PATTERN_SEPARATOR_SYMBOL),\n                    'PERCENT_SYMBOL' => $c->getSymbol(\\NumberFormatter::PERCENT_SYMBOL),\n                    'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\\NumberFormatter::ZERO_DIGIT_SYMBOL),\n                    'DIGIT_SYMBOL' => $c->getSymbol(\\NumberFormatter::DIGIT_SYMBOL),\n                    'MINUS_SIGN_SYMBOL' => $c->getSymbol(\\NumberFormatter::MINUS_SIGN_SYMBOL),\n                    'PLUS_SIGN_SYMBOL' => $c->getSymbol(\\NumberFormatter::PLUS_SIGN_SYMBOL),\n                    'CURRENCY_SYMBOL' => $c->getSymbol(\\NumberFormatter::CURRENCY_SYMBOL),\n                    'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\\NumberFormatter::INTL_CURRENCY_SYMBOL),\n                    'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::MONETARY_SEPARATOR_SYMBOL),\n                    'EXPONENTIAL_SYMBOL' => $c->getSymbol(\\NumberFormatter::EXPONENTIAL_SYMBOL),\n                    'PERMILL_SYMBOL' => $c->getSymbol(\\NumberFormatter::PERMILL_SYMBOL),\n                    'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\\NumberFormatter::PAD_ESCAPE_SYMBOL),\n                    'INFINITY_SYMBOL' => $c->getSymbol(\\NumberFormatter::INFINITY_SYMBOL),\n                    'NAN_SYMBOL' => $c->getSymbol(\\NumberFormatter::NAN_SYMBOL),\n                    'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL),\n                    'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL),\n                ]\n             ),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    public static function castIntlTimeZone(\\IntlTimeZone $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(),\n            Caster::PREFIX_VIRTUAL.'id' => $c->getID(),\n            Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(),\n        ];\n\n        if ($c->useDaylightTime()) {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(),\n            ];\n        }\n\n        return self::castError($c, $a);\n    }\n\n    public static function castIntlCalendar(\\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'type' => $c->getType(),\n            Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(),\n            Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(),\n            Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(),\n            Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(),\n            Caster::PREFIX_VIRTUAL.'time' => $c->getTime(),\n            Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(),\n            Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(),\n            Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    public static function castIntlDateFormatter(\\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),\n            Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),\n            Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(),\n            Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(),\n            Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(),\n            Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(),\n            Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(),\n            Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(),\n        ];\n\n        return self::castError($c, $a);\n    }\n\n    private static function castError(object $c, array $a): array\n    {\n        if ($errorCode = $c->getErrorCode()) {\n            $a += [\n                Caster::PREFIX_VIRTUAL.'error_code' => $errorCode,\n                Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(),\n            ];\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/LinkStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\n/**\n * Represents a file or a URL.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass LinkStub extends ConstStub\n{\n    public $inVendor = false;\n\n    private static $vendorRoots;\n    private static $composerRoots;\n\n    public function __construct(string $label, int $line = 0, string $href = null)\n    {\n        $this->value = $label;\n\n        if (null === $href) {\n            $href = $label;\n        }\n        if (!\\is_string($href)) {\n            return;\n        }\n        if (str_starts_with($href, 'file://')) {\n            if ($href === $label) {\n                $label = substr($label, 7);\n            }\n            $href = substr($href, 7);\n        } elseif (str_contains($href, '://')) {\n            $this->attr['href'] = $href;\n\n            return;\n        }\n        if (!is_file($href)) {\n            return;\n        }\n        if ($line) {\n            $this->attr['line'] = $line;\n        }\n        if ($label !== $this->attr['file'] = realpath($href) ?: $href) {\n            return;\n        }\n        if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) {\n            $this->attr['ellipsis'] = \\strlen($href) - \\strlen($composerRoot) + 1;\n            $this->attr['ellipsis-type'] = 'path';\n            $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \\strlen(implode('', \\array_slice(explode(\\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0);\n        } elseif (3 < \\count($ellipsis = explode(\\DIRECTORY_SEPARATOR, $href))) {\n            $this->attr['ellipsis'] = 2 + \\strlen(implode('', \\array_slice($ellipsis, -2)));\n            $this->attr['ellipsis-type'] = 'path';\n            $this->attr['ellipsis-tail'] = 1;\n        }\n    }\n\n    private function getComposerRoot(string $file, bool &$inVendor)\n    {\n        if (null === self::$vendorRoots) {\n            self::$vendorRoots = [];\n\n            foreach (get_declared_classes() as $class) {\n                if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {\n                    $r = new \\ReflectionClass($class);\n                    $v = \\dirname($r->getFileName(), 2);\n                    if (is_file($v.'/composer/installed.json')) {\n                        self::$vendorRoots[] = $v.\\DIRECTORY_SEPARATOR;\n                    }\n                }\n            }\n        }\n        $inVendor = false;\n\n        if (isset(self::$composerRoots[$dir = \\dirname($file)])) {\n            return self::$composerRoots[$dir];\n        }\n\n        foreach (self::$vendorRoots as $root) {\n            if ($inVendor = str_starts_with($file, $root)) {\n                return $root;\n            }\n        }\n\n        $parent = $dir;\n        while (!@is_file($parent.'/composer.json')) {\n            if (!@file_exists($parent)) {\n                // open_basedir restriction in effect\n                break;\n            }\n            if ($parent === \\dirname($parent)) {\n                return self::$composerRoots[$dir] = false;\n            }\n\n            $parent = \\dirname($parent);\n        }\n\n        return self::$composerRoots[$dir] = $parent.\\DIRECTORY_SEPARATOR;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/MemcachedCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>\n *\n * @final\n */\nclass MemcachedCaster\n{\n    private static $optionConstants;\n    private static $defaultOptions;\n\n    public static function castMemcached(\\Memcached $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(),\n            Caster::PREFIX_VIRTUAL.'options' => new EnumStub(\n                self::getNonDefaultOptions($c)\n            ),\n        ];\n\n        return $a;\n    }\n\n    private static function getNonDefaultOptions(\\Memcached $c): array\n    {\n        self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions();\n        self::$optionConstants = self::$optionConstants ?? self::getOptionConstants();\n\n        $nonDefaultOptions = [];\n        foreach (self::$optionConstants as $constantKey => $value) {\n            if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) {\n                $nonDefaultOptions[$constantKey] = $option;\n            }\n        }\n\n        return $nonDefaultOptions;\n    }\n\n    private static function discoverDefaultOptions(): array\n    {\n        $defaultMemcached = new \\Memcached();\n        $defaultMemcached->addServer('127.0.0.1', 11211);\n\n        $defaultOptions = [];\n        self::$optionConstants = self::$optionConstants ?? self::getOptionConstants();\n\n        foreach (self::$optionConstants as $constantKey => $value) {\n            $defaultOptions[$constantKey] = $defaultMemcached->getOption($value);\n        }\n\n        return $defaultOptions;\n    }\n\n    private static function getOptionConstants(): array\n    {\n        $reflectedMemcached = new \\ReflectionClass(\\Memcached::class);\n\n        $optionConstants = [];\n        foreach ($reflectedMemcached->getConstants() as $constantKey => $value) {\n            if (str_starts_with($constantKey, 'OPT_')) {\n                $optionConstants[$constantKey] = $value;\n            }\n        }\n\n        return $optionConstants;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/MysqliCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @internal\n */\nfinal class MysqliCaster\n{\n    public static function castMysqliDriver(\\mysqli_driver $c, array $a, Stub $stub, bool $isNested): array\n    {\n        foreach ($a as $k => $v) {\n            if (isset($c->$k)) {\n                $a[$k] = $c->$k;\n            }\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/PdoCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts PDO related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass PdoCaster\n{\n    private const PDO_ATTRIBUTES = [\n        'CASE' => [\n            \\PDO::CASE_LOWER => 'LOWER',\n            \\PDO::CASE_NATURAL => 'NATURAL',\n            \\PDO::CASE_UPPER => 'UPPER',\n        ],\n        'ERRMODE' => [\n            \\PDO::ERRMODE_SILENT => 'SILENT',\n            \\PDO::ERRMODE_WARNING => 'WARNING',\n            \\PDO::ERRMODE_EXCEPTION => 'EXCEPTION',\n        ],\n        'TIMEOUT',\n        'PREFETCH',\n        'AUTOCOMMIT',\n        'PERSISTENT',\n        'DRIVER_NAME',\n        'SERVER_INFO',\n        'ORACLE_NULLS' => [\n            \\PDO::NULL_NATURAL => 'NATURAL',\n            \\PDO::NULL_EMPTY_STRING => 'EMPTY_STRING',\n            \\PDO::NULL_TO_STRING => 'TO_STRING',\n        ],\n        'CLIENT_VERSION',\n        'SERVER_VERSION',\n        'STATEMENT_CLASS',\n        'EMULATE_PREPARES',\n        'CONNECTION_STATUS',\n        'STRINGIFY_FETCHES',\n        'DEFAULT_FETCH_MODE' => [\n            \\PDO::FETCH_ASSOC => 'ASSOC',\n            \\PDO::FETCH_BOTH => 'BOTH',\n            \\PDO::FETCH_LAZY => 'LAZY',\n            \\PDO::FETCH_NUM => 'NUM',\n            \\PDO::FETCH_OBJ => 'OBJ',\n        ],\n    ];\n\n    public static function castPdo(\\PDO $c, array $a, Stub $stub, bool $isNested)\n    {\n        $attr = [];\n        $errmode = $c->getAttribute(\\PDO::ATTR_ERRMODE);\n        $c->setAttribute(\\PDO::ATTR_ERRMODE, \\PDO::ERRMODE_EXCEPTION);\n\n        foreach (self::PDO_ATTRIBUTES as $k => $v) {\n            if (!isset($k[0])) {\n                $k = $v;\n                $v = [];\n            }\n\n            try {\n                $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\\constant('PDO::ATTR_'.$k));\n                if ($v && isset($v[$attr[$k]])) {\n                    $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]);\n                }\n            } catch (\\Exception $e) {\n            }\n        }\n        if (isset($attr[$k = 'STATEMENT_CLASS'][1])) {\n            if ($attr[$k][1]) {\n                $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]);\n            }\n            $attr[$k][0] = new ClassStub($attr[$k][0]);\n        }\n\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $a += [\n            $prefix.'inTransaction' => method_exists($c, 'inTransaction'),\n            $prefix.'errorInfo' => $c->errorInfo(),\n            $prefix.'attributes' => new EnumStub($attr),\n        ];\n\n        if ($a[$prefix.'inTransaction']) {\n            $a[$prefix.'inTransaction'] = $c->inTransaction();\n        } else {\n            unset($a[$prefix.'inTransaction']);\n        }\n\n        if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) {\n            unset($a[$prefix.'errorInfo']);\n        }\n\n        $c->setAttribute(\\PDO::ATTR_ERRMODE, $errmode);\n\n        return $a;\n    }\n\n    public static function castPdoStatement(\\PDOStatement $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $a[$prefix.'errorInfo'] = $c->errorInfo();\n\n        if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) {\n            unset($a[$prefix.'errorInfo']);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/PgSqlCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts pqsql resources to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass PgSqlCaster\n{\n    private const PARAM_CODES = [\n        'server_encoding',\n        'client_encoding',\n        'is_superuser',\n        'session_authorization',\n        'DateStyle',\n        'TimeZone',\n        'IntervalStyle',\n        'integer_datetimes',\n        'application_name',\n        'standard_conforming_strings',\n    ];\n\n    private const TRANSACTION_STATUS = [\n        \\PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE',\n        \\PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE',\n        \\PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS',\n        \\PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR',\n        \\PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN',\n    ];\n\n    private const RESULT_STATUS = [\n        \\PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY',\n        \\PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK',\n        \\PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK',\n        \\PGSQL_COPY_OUT => 'PGSQL_COPY_OUT',\n        \\PGSQL_COPY_IN => 'PGSQL_COPY_IN',\n        \\PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE',\n        \\PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR',\n        \\PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR',\n    ];\n\n    private const DIAG_CODES = [\n        'severity' => \\PGSQL_DIAG_SEVERITY,\n        'sqlstate' => \\PGSQL_DIAG_SQLSTATE,\n        'message' => \\PGSQL_DIAG_MESSAGE_PRIMARY,\n        'detail' => \\PGSQL_DIAG_MESSAGE_DETAIL,\n        'hint' => \\PGSQL_DIAG_MESSAGE_HINT,\n        'statement position' => \\PGSQL_DIAG_STATEMENT_POSITION,\n        'internal position' => \\PGSQL_DIAG_INTERNAL_POSITION,\n        'internal query' => \\PGSQL_DIAG_INTERNAL_QUERY,\n        'context' => \\PGSQL_DIAG_CONTEXT,\n        'file' => \\PGSQL_DIAG_SOURCE_FILE,\n        'line' => \\PGSQL_DIAG_SOURCE_LINE,\n        'function' => \\PGSQL_DIAG_SOURCE_FUNCTION,\n    ];\n\n    public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested)\n    {\n        $a['seek position'] = pg_lo_tell($lo);\n\n        return $a;\n    }\n\n    public static function castLink($link, array $a, Stub $stub, bool $isNested)\n    {\n        $a['status'] = pg_connection_status($link);\n        $a['status'] = new ConstStub(\\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']);\n        $a['busy'] = pg_connection_busy($link);\n\n        $a['transaction'] = pg_transaction_status($link);\n        if (isset(self::TRANSACTION_STATUS[$a['transaction']])) {\n            $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']);\n        }\n\n        $a['pid'] = pg_get_pid($link);\n        $a['last error'] = pg_last_error($link);\n        $a['last notice'] = pg_last_notice($link);\n        $a['host'] = pg_host($link);\n        $a['port'] = pg_port($link);\n        $a['dbname'] = pg_dbname($link);\n        $a['options'] = pg_options($link);\n        $a['version'] = pg_version($link);\n\n        foreach (self::PARAM_CODES as $v) {\n            if (false !== $s = pg_parameter_status($link, $v)) {\n                $a['param'][$v] = $s;\n            }\n        }\n\n        $a['param']['client_encoding'] = pg_client_encoding($link);\n        $a['param'] = new EnumStub($a['param']);\n\n        return $a;\n    }\n\n    public static function castResult($result, array $a, Stub $stub, bool $isNested)\n    {\n        $a['num rows'] = pg_num_rows($result);\n        $a['status'] = pg_result_status($result);\n        if (isset(self::RESULT_STATUS[$a['status']])) {\n            $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']);\n        }\n        $a['command-completion tag'] = pg_result_status($result, \\PGSQL_STATUS_STRING);\n\n        if (-1 === $a['num rows']) {\n            foreach (self::DIAG_CODES as $k => $v) {\n                $a['error'][$k] = pg_result_error_field($result, $v);\n            }\n        }\n\n        $a['affected rows'] = pg_affected_rows($result);\n        $a['last OID'] = pg_last_oid($result);\n\n        $fields = pg_num_fields($result);\n\n        for ($i = 0; $i < $fields; ++$i) {\n            $field = [\n                'name' => pg_field_name($result, $i),\n                'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)),\n                'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)),\n                'nullable' => (bool) pg_field_is_null($result, $i),\n                'storage' => pg_field_size($result, $i).' bytes',\n                'display' => pg_field_prtlen($result, $i).' chars',\n            ];\n            if (' (OID: )' === $field['table']) {\n                $field['table'] = null;\n            }\n            if ('-1 bytes' === $field['storage']) {\n                $field['storage'] = 'variable size';\n            } elseif ('1 bytes' === $field['storage']) {\n                $field['storage'] = '1 byte';\n            }\n            if ('1 chars' === $field['display']) {\n                $field['display'] = '1 char';\n            }\n            $a['fields'][] = new EnumStub($field);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse ProxyManager\\Proxy\\ProxyInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass ProxyManagerCaster\n{\n    public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested)\n    {\n        if ($parent = get_parent_class($c)) {\n            $stub->class .= ' - '.$parent;\n        }\n        $stub->class .= '@proxy';\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/RdKafkaCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse RdKafka\\Conf;\nuse RdKafka\\Exception as RdKafkaException;\nuse RdKafka\\KafkaConsumer;\nuse RdKafka\\Message;\nuse RdKafka\\Metadata\\Broker as BrokerMetadata;\nuse RdKafka\\Metadata\\Collection as CollectionMetadata;\nuse RdKafka\\Metadata\\Partition as PartitionMetadata;\nuse RdKafka\\Metadata\\Topic as TopicMetadata;\nuse RdKafka\\Topic;\nuse RdKafka\\TopicConf;\nuse RdKafka\\TopicPartition;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts RdKafka related classes to array representation.\n *\n * @author Romain Neutron <imprec@gmail.com>\n */\nclass RdKafkaCaster\n{\n    public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        try {\n            $assignment = $c->getAssignment();\n        } catch (RdKafkaException $e) {\n            $assignment = [];\n        }\n\n        $a += [\n            $prefix.'subscription' => $c->getSubscription(),\n            $prefix.'assignment' => $assignment,\n        ];\n\n        $a += self::extractMetadata($c);\n\n        return $a;\n    }\n\n    public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'name' => $c->getName(),\n        ];\n\n        return $a;\n    }\n\n    public static function castTopicPartition(TopicPartition $c, array $a)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'offset' => $c->getOffset(),\n            $prefix.'partition' => $c->getPartition(),\n            $prefix.'topic' => $c->getTopic(),\n        ];\n\n        return $a;\n    }\n\n    public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'errstr' => $c->errstr(),\n        ];\n\n        return $a;\n    }\n\n    public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        foreach ($c->dump() as $key => $value) {\n            $a[$prefix.$key] = $value;\n        }\n\n        return $a;\n    }\n\n    public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        foreach ($c->dump() as $key => $value) {\n            $a[$prefix.$key] = $value;\n        }\n\n        return $a;\n    }\n\n    public static function castRdKafka(\\RdKafka $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'out_q_len' => $c->getOutQLen(),\n        ];\n\n        $a += self::extractMetadata($c);\n\n        return $a;\n    }\n\n    public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a += iterator_to_array($c);\n\n        return $a;\n    }\n\n    public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'name' => $c->getTopic(),\n            $prefix.'partitions' => $c->getPartitions(),\n        ];\n\n        return $a;\n    }\n\n    public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'id' => $c->getId(),\n            $prefix.'err' => $c->getErr(),\n            $prefix.'leader' => $c->getLeader(),\n        ];\n\n        return $a;\n    }\n\n    public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        $a += [\n            $prefix.'id' => $c->getId(),\n            $prefix.'host' => $c->getHost(),\n            $prefix.'port' => $c->getPort(),\n        ];\n\n        return $a;\n    }\n\n    private static function extractMetadata($c)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        try {\n            $m = $c->getMetadata(true, null, 500);\n        } catch (RdKafkaException $e) {\n            return [];\n        }\n\n        return [\n            $prefix.'orig_broker_id' => $m->getOrigBrokerId(),\n            $prefix.'orig_broker_name' => $m->getOrigBrokerName(),\n            $prefix.'brokers' => $m->getBrokers(),\n            $prefix.'topics' => $m->getTopics(),\n        ];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/RedisCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Redis class from ext-redis to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass RedisCaster\n{\n    private const SERIALIZERS = [\n        \\Redis::SERIALIZER_NONE => 'NONE',\n        \\Redis::SERIALIZER_PHP => 'PHP',\n        2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY\n    ];\n\n    private const MODES = [\n        \\Redis::ATOMIC => 'ATOMIC',\n        \\Redis::MULTI => 'MULTI',\n        \\Redis::PIPELINE => 'PIPELINE',\n    ];\n\n    private const COMPRESSION_MODES = [\n        0 => 'NONE', // Redis::COMPRESSION_NONE\n        1 => 'LZF',  // Redis::COMPRESSION_LZF\n    ];\n\n    private const FAILOVER_OPTIONS = [\n        \\RedisCluster::FAILOVER_NONE => 'NONE',\n        \\RedisCluster::FAILOVER_ERROR => 'ERROR',\n        \\RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE',\n        \\RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES',\n    ];\n\n    public static function castRedis(\\Redis $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if (!$connected = $c->isConnected()) {\n            return $a + [\n                $prefix.'isConnected' => $connected,\n            ];\n        }\n\n        $mode = $c->getMode();\n\n        return $a + [\n            $prefix.'isConnected' => $connected,\n            $prefix.'host' => $c->getHost(),\n            $prefix.'port' => $c->getPort(),\n            $prefix.'auth' => $c->getAuth(),\n            $prefix.'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode,\n            $prefix.'dbNum' => $c->getDbNum(),\n            $prefix.'timeout' => $c->getTimeout(),\n            $prefix.'lastError' => $c->getLastError(),\n            $prefix.'persistentId' => $c->getPersistentID(),\n            $prefix.'options' => self::getRedisOptions($c),\n        ];\n    }\n\n    public static function castRedisArray(\\RedisArray $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        return $a + [\n            $prefix.'hosts' => $c->_hosts(),\n            $prefix.'function' => ClassStub::wrapCallable($c->_function()),\n            $prefix.'lastError' => $c->getLastError(),\n            $prefix.'options' => self::getRedisOptions($c),\n        ];\n    }\n\n    public static function castRedisCluster(\\RedisCluster $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $failover = $c->getOption(\\RedisCluster::OPT_SLAVE_FAILOVER);\n\n        $a += [\n            $prefix.'_masters' => $c->_masters(),\n            $prefix.'_redir' => $c->_redir(),\n            $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()),\n            $prefix.'lastError' => $c->getLastError(),\n            $prefix.'options' => self::getRedisOptions($c, [\n                'SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover,\n            ]),\n        ];\n\n        return $a;\n    }\n\n    /**\n     * @param \\Redis|\\RedisArray|\\RedisCluster $redis\n     */\n    private static function getRedisOptions($redis, array $options = []): EnumStub\n    {\n        $serializer = $redis->getOption(\\Redis::OPT_SERIALIZER);\n        if (\\is_array($serializer)) {\n            foreach ($serializer as &$v) {\n                if (isset(self::SERIALIZERS[$v])) {\n                    $v = new ConstStub(self::SERIALIZERS[$v], $v);\n                }\n            }\n        } elseif (isset(self::SERIALIZERS[$serializer])) {\n            $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer);\n        }\n\n        $compression = \\defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\\Redis::OPT_COMPRESSION) : 0;\n        if (\\is_array($compression)) {\n            foreach ($compression as &$v) {\n                if (isset(self::COMPRESSION_MODES[$v])) {\n                    $v = new ConstStub(self::COMPRESSION_MODES[$v], $v);\n                }\n            }\n        } elseif (isset(self::COMPRESSION_MODES[$compression])) {\n            $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression);\n        }\n\n        $retry = \\defined('Redis::OPT_SCAN') ? $redis->getOption(\\Redis::OPT_SCAN) : 0;\n        if (\\is_array($retry)) {\n            foreach ($retry as &$v) {\n                $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v);\n            }\n        } else {\n            $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry);\n        }\n\n        $options += [\n            'TCP_KEEPALIVE' => \\defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\\Redis::OPT_TCP_KEEPALIVE) : 0,\n            'READ_TIMEOUT' => $redis->getOption(\\Redis::OPT_READ_TIMEOUT),\n            'COMPRESSION' => $compression,\n            'SERIALIZER' => $serializer,\n            'PREFIX' => $redis->getOption(\\Redis::OPT_PREFIX),\n            'SCAN' => $retry,\n        ];\n\n        return new EnumStub($options);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ReflectionCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts Reflector related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass ReflectionCaster\n{\n    public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo'];\n\n    private const EXTRA_MAP = [\n        'docComment' => 'getDocComment',\n        'extension' => 'getExtensionName',\n        'isDisabled' => 'isDisabled',\n        'isDeprecated' => 'isDeprecated',\n        'isInternal' => 'isInternal',\n        'isUserDefined' => 'isUserDefined',\n        'isGenerator' => 'isGenerator',\n        'isVariadic' => 'isVariadic',\n    ];\n\n    public static function castClosure(\\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $c = new \\ReflectionFunction($c);\n\n        $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);\n\n        if (!str_contains($c->name, '{closure}')) {\n            $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name;\n            unset($a[$prefix.'class']);\n        }\n        unset($a[$prefix.'extra']);\n\n        $stub->class .= self::getSignature($a);\n\n        if ($f = $c->getFileName()) {\n            $stub->attr['file'] = $f;\n            $stub->attr['line'] = $c->getStartLine();\n        }\n\n        unset($a[$prefix.'parameters']);\n\n        if ($filter & Caster::EXCLUDE_VERBOSE) {\n            $stub->cut += ($c->getFileName() ? 2 : 0) + \\count($a);\n\n            return [];\n        }\n\n        if ($f) {\n            $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());\n            $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();\n        }\n\n        return $a;\n    }\n\n    public static function unsetClosureFileInfo(\\Closure $c, array $a)\n    {\n        unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']);\n\n        return $a;\n    }\n\n    public static function castGenerator(\\Generator $c, array $a, Stub $stub, bool $isNested)\n    {\n        // Cannot create ReflectionGenerator based on a terminated Generator\n        try {\n            $reflectionGenerator = new \\ReflectionGenerator($c);\n        } catch (\\Exception $e) {\n            $a[Caster::PREFIX_VIRTUAL.'closed'] = true;\n\n            return $a;\n        }\n\n        return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);\n    }\n\n    public static function castType(\\ReflectionType $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($c instanceof \\ReflectionNamedType || \\PHP_VERSION_ID < 80000) {\n            $a += [\n                $prefix.'name' => $c instanceof \\ReflectionNamedType ? $c->getName() : (string) $c,\n                $prefix.'allowsNull' => $c->allowsNull(),\n                $prefix.'isBuiltin' => $c->isBuiltin(),\n            ];\n        } elseif ($c instanceof \\ReflectionUnionType || $c instanceof \\ReflectionIntersectionType) {\n            $a[$prefix.'allowsNull'] = $c->allowsNull();\n            self::addMap($a, $c, [\n                'types' => 'getTypes',\n            ]);\n        } else {\n            $a[$prefix.'allowsNull'] = $c->allowsNull();\n        }\n\n        return $a;\n    }\n\n    public static function castAttribute(\\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)\n    {\n        self::addMap($a, $c, [\n            'name' => 'getName',\n            'arguments' => 'getArguments',\n        ]);\n\n        return $a;\n    }\n\n    public static function castReflectionGenerator(\\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($c->getThis()) {\n            $a[$prefix.'this'] = new CutStub($c->getThis());\n        }\n        $function = $c->getFunction();\n        $frame = [\n            'class' => $function->class ?? null,\n            'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null,\n            'function' => $function->name,\n            'file' => $c->getExecutingFile(),\n            'line' => $c->getExecutingLine(),\n        ];\n        if ($trace = $c->getTrace(\\DEBUG_BACKTRACE_IGNORE_ARGS)) {\n            $function = new \\ReflectionGenerator($c->getExecutingGenerator());\n            array_unshift($trace, [\n                'function' => 'yield',\n                'file' => $function->getExecutingFile(),\n                'line' => $function->getExecutingLine() - (int) (\\PHP_VERSION_ID < 80100),\n            ]);\n            $trace[] = $frame;\n            $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);\n        } else {\n            $function = new FrameStub($frame, false, true);\n            $function = ExceptionCaster::castFrameStub($function, [], $function, true);\n            $a[$prefix.'executing'] = $function[$prefix.'src'];\n        }\n\n        $a[Caster::PREFIX_VIRTUAL.'closed'] = false;\n\n        return $a;\n    }\n\n    public static function castClass(\\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        if ($n = \\Reflection::getModifierNames($c->getModifiers())) {\n            $a[$prefix.'modifiers'] = implode(' ', $n);\n        }\n\n        self::addMap($a, $c, [\n            'extends' => 'getParentClass',\n            'implements' => 'getInterfaceNames',\n            'constants' => 'getReflectionConstants',\n        ]);\n\n        foreach ($c->getProperties() as $n) {\n            $a[$prefix.'properties'][$n->name] = $n;\n        }\n\n        foreach ($c->getMethods() as $n) {\n            $a[$prefix.'methods'][$n->name] = $n;\n        }\n\n        self::addAttributes($a, $c, $prefix);\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {\n            self::addExtra($a, $c);\n        }\n\n        return $a;\n    }\n\n    public static function castFunctionAbstract(\\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        self::addMap($a, $c, [\n            'returnsReference' => 'returnsReference',\n            'returnType' => 'getReturnType',\n            'class' => 'getClosureScopeClass',\n            'this' => 'getClosureThis',\n        ]);\n\n        if (isset($a[$prefix.'returnType'])) {\n            $v = $a[$prefix.'returnType'];\n            $v = $v instanceof \\ReflectionNamedType ? $v->getName() : (string) $v;\n            $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \\ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);\n        }\n        if (isset($a[$prefix.'class'])) {\n            $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']);\n        }\n        if (isset($a[$prefix.'this'])) {\n            $a[$prefix.'this'] = new CutStub($a[$prefix.'this']);\n        }\n\n        foreach ($c->getParameters() as $v) {\n            $k = '$'.$v->name;\n            if ($v->isVariadic()) {\n                $k = '...'.$k;\n            }\n            if ($v->isPassedByReference()) {\n                $k = '&'.$k;\n            }\n            $a[$prefix.'parameters'][$k] = $v;\n        }\n        if (isset($a[$prefix.'parameters'])) {\n            $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']);\n        }\n\n        self::addAttributes($a, $c, $prefix);\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {\n            foreach ($v as $k => &$v) {\n                if (\\is_object($v)) {\n                    $a[$prefix.'use']['$'.$k] = new CutStub($v);\n                } else {\n                    $a[$prefix.'use']['$'.$k] = &$v;\n                }\n            }\n            unset($v);\n            $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']);\n        }\n\n        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {\n            self::addExtra($a, $c);\n        }\n\n        return $a;\n    }\n\n    public static function castClassConstant(\\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \\Reflection::getModifierNames($c->getModifiers()));\n        $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue();\n\n        self::addAttributes($a, $c);\n\n        return $a;\n    }\n\n    public static function castMethod(\\ReflectionMethod $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \\Reflection::getModifierNames($c->getModifiers()));\n\n        return $a;\n    }\n\n    public static function castParameter(\\ReflectionParameter $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        self::addMap($a, $c, [\n            'position' => 'getPosition',\n            'isVariadic' => 'isVariadic',\n            'byReference' => 'isPassedByReference',\n            'allowsNull' => 'allowsNull',\n        ]);\n\n        self::addAttributes($a, $c, $prefix);\n\n        if ($v = $c->getType()) {\n            $a[$prefix.'typeHint'] = $v instanceof \\ReflectionNamedType ? $v->getName() : (string) $v;\n        }\n\n        if (isset($a[$prefix.'typeHint'])) {\n            $v = $a[$prefix.'typeHint'];\n            $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);\n        } else {\n            unset($a[$prefix.'allowsNull']);\n        }\n\n        if ($c->isOptional()) {\n            try {\n                $a[$prefix.'default'] = $v = $c->getDefaultValue();\n                if ($c->isDefaultValueConstant()) {\n                    $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);\n                }\n                if (null === $v) {\n                    unset($a[$prefix.'allowsNull']);\n                }\n            } catch (\\ReflectionException $e) {\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castProperty(\\ReflectionProperty $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \\Reflection::getModifierNames($c->getModifiers()));\n\n        self::addAttributes($a, $c);\n        self::addExtra($a, $c);\n\n        return $a;\n    }\n\n    public static function castReference(\\ReflectionReference $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId();\n\n        return $a;\n    }\n\n    public static function castExtension(\\ReflectionExtension $c, array $a, Stub $stub, bool $isNested)\n    {\n        self::addMap($a, $c, [\n            'version' => 'getVersion',\n            'dependencies' => 'getDependencies',\n            'iniEntries' => 'getIniEntries',\n            'isPersistent' => 'isPersistent',\n            'isTemporary' => 'isTemporary',\n            'constants' => 'getConstants',\n            'functions' => 'getFunctions',\n            'classes' => 'getClasses',\n        ]);\n\n        return $a;\n    }\n\n    public static function castZendExtension(\\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested)\n    {\n        self::addMap($a, $c, [\n            'version' => 'getVersion',\n            'author' => 'getAuthor',\n            'copyright' => 'getCopyright',\n            'url' => 'getURL',\n        ]);\n\n        return $a;\n    }\n\n    public static function getSignature(array $a)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $signature = '';\n\n        if (isset($a[$prefix.'parameters'])) {\n            foreach ($a[$prefix.'parameters']->value as $k => $param) {\n                $signature .= ', ';\n                if ($type = $param->getType()) {\n                    if (!$type instanceof \\ReflectionNamedType) {\n                        $signature .= $type.' ';\n                    } else {\n                        if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) {\n                            $signature .= '?';\n                        }\n                        $signature .= substr(strrchr('\\\\'.$type->getName(), '\\\\'), 1).' ';\n                    }\n                }\n                $signature .= $k;\n\n                if (!$param->isDefaultValueAvailable()) {\n                    continue;\n                }\n                $v = $param->getDefaultValue();\n                $signature .= ' = ';\n\n                if ($param->isDefaultValueConstant()) {\n                    $signature .= substr(strrchr('\\\\'.$param->getDefaultValueConstantName(), '\\\\'), 1);\n                } elseif (null === $v) {\n                    $signature .= 'null';\n                } elseif (\\is_array($v)) {\n                    $signature .= $v ? '[…'.\\count($v).']' : '[]';\n                } elseif (\\is_string($v)) {\n                    $signature .= 10 > \\strlen($v) && !str_contains($v, '\\\\') ? \"'{$v}'\" : \"'…\".\\strlen($v).\"'\";\n                } elseif (\\is_bool($v)) {\n                    $signature .= $v ? 'true' : 'false';\n                } elseif (\\is_object($v)) {\n                    $signature .= 'new '.substr(strrchr('\\\\'.get_debug_type($v), '\\\\'), 1);\n                } else {\n                    $signature .= $v;\n                }\n            }\n        }\n        $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')';\n\n        if (isset($a[$prefix.'returnType'])) {\n            $signature .= ': '.substr(strrchr('\\\\'.$a[$prefix.'returnType'], '\\\\'), 1);\n        }\n\n        return $signature;\n    }\n\n    private static function addExtra(array &$a, \\Reflector $c)\n    {\n        $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : [];\n\n        if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {\n            $x['file'] = new LinkStub($m, $c->getStartLine());\n            $x['line'] = $c->getStartLine().' to '.$c->getEndLine();\n        }\n\n        self::addMap($x, $c, self::EXTRA_MAP, '');\n\n        if ($x) {\n            $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x);\n        }\n    }\n\n    private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)\n    {\n        foreach ($map as $k => $m) {\n            if (\\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) {\n                continue;\n            }\n\n            if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) {\n                $a[$prefix.$k] = $m instanceof \\Reflector ? $m->name : $m;\n            }\n        }\n    }\n\n    private static function addAttributes(array &$a, \\Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void\n    {\n        if (\\PHP_VERSION_ID >= 80000) {\n            foreach ($c->getAttributes() as $n) {\n                $a[$prefix.'attributes'][] = $n;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/ResourceCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts common resource types to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass ResourceCaster\n{\n    /**\n     * @param \\CurlHandle|resource $h\n     */\n    public static function castCurl($h, array $a, Stub $stub, bool $isNested): array\n    {\n        return curl_getinfo($h);\n    }\n\n    public static function castDba($dba, array $a, Stub $stub, bool $isNested)\n    {\n        $list = dba_list();\n        $a['file'] = $list[(int) $dba];\n\n        return $a;\n    }\n\n    public static function castProcess($process, array $a, Stub $stub, bool $isNested)\n    {\n        return proc_get_status($process);\n    }\n\n    public static function castStream($stream, array $a, Stub $stub, bool $isNested)\n    {\n        $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);\n        if ($a['uri'] ?? false) {\n            $a['uri'] = new LinkStub($a['uri']);\n        }\n\n        return $a;\n    }\n\n    public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested)\n    {\n        return @stream_context_get_params($stream) ?: $a;\n    }\n\n    public static function castGd($gd, array $a, Stub $stub, bool $isNested)\n    {\n        $a['size'] = imagesx($gd).'x'.imagesy($gd);\n        $a['trueColor'] = imageistruecolor($gd);\n\n        return $a;\n    }\n\n    public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested)\n    {\n        $a['host'] = mysql_get_host_info($h);\n        $a['protocol'] = mysql_get_proto_info($h);\n        $a['server'] = mysql_get_server_info($h);\n\n        return $a;\n    }\n\n    public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested)\n    {\n        $stub->cut = -1;\n        $info = openssl_x509_parse($h, false);\n\n        $pin = openssl_pkey_get_public($h);\n        $pin = openssl_pkey_get_details($pin)['key'];\n        $pin = \\array_slice(explode(\"\\n\", $pin), 1, -2);\n        $pin = base64_decode(implode('', $pin));\n        $pin = base64_encode(hash('sha256', $pin, true));\n\n        $a += [\n            'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])),\n            'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])),\n            'expiry' => new ConstStub(date(\\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']),\n            'fingerprint' => new EnumStub([\n                'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)),\n                'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)),\n                'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)),\n                'pin-sha256' => new ConstStub($pin),\n            ]),\n        ];\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/SplCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts SPL related classes to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass SplCaster\n{\n    private const SPL_FILE_OBJECT_FLAGS = [\n        \\SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE',\n        \\SplFileObject::READ_AHEAD => 'READ_AHEAD',\n        \\SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY',\n        \\SplFileObject::READ_CSV => 'READ_CSV',\n    ];\n\n    public static function castArrayObject(\\ArrayObject $c, array $a, Stub $stub, bool $isNested)\n    {\n        return self::castSplArray($c, $a, $stub, $isNested);\n    }\n\n    public static function castArrayIterator(\\ArrayIterator $c, array $a, Stub $stub, bool $isNested)\n    {\n        return self::castSplArray($c, $a, $stub, $isNested);\n    }\n\n    public static function castHeap(\\Iterator $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c),\n        ];\n\n        return $a;\n    }\n\n    public static function castDoublyLinkedList(\\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested)\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $mode = $c->getIteratorMode();\n        $c->setIteratorMode(\\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\\SplDoublyLinkedList::IT_MODE_DELETE);\n\n        $a += [\n            $prefix.'mode' => new ConstStub((($mode & \\SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \\SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode),\n            $prefix.'dllist' => iterator_to_array($c),\n        ];\n        $c->setIteratorMode($mode);\n\n        return $a;\n    }\n\n    public static function castFileInfo(\\SplFileInfo $c, array $a, Stub $stub, bool $isNested)\n    {\n        static $map = [\n            'path' => 'getPath',\n            'filename' => 'getFilename',\n            'basename' => 'getBasename',\n            'pathname' => 'getPathname',\n            'extension' => 'getExtension',\n            'realPath' => 'getRealPath',\n            'aTime' => 'getATime',\n            'mTime' => 'getMTime',\n            'cTime' => 'getCTime',\n            'inode' => 'getInode',\n            'size' => 'getSize',\n            'perms' => 'getPerms',\n            'owner' => 'getOwner',\n            'group' => 'getGroup',\n            'type' => 'getType',\n            'writable' => 'isWritable',\n            'readable' => 'isReadable',\n            'executable' => 'isExecutable',\n            'file' => 'isFile',\n            'dir' => 'isDir',\n            'link' => 'isLink',\n            'linkTarget' => 'getLinkTarget',\n        ];\n\n        $prefix = Caster::PREFIX_VIRTUAL;\n        unset($a[\"\\0SplFileInfo\\0fileName\"]);\n        unset($a[\"\\0SplFileInfo\\0pathName\"]);\n\n        if (\\PHP_VERSION_ID < 80000) {\n            if (false === $c->getPathname()) {\n                $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';\n\n                return $a;\n            }\n        } else {\n            try {\n                $c->isReadable();\n            } catch (\\RuntimeException $e) {\n                if ('Object not initialized' !== $e->getMessage()) {\n                    throw $e;\n                }\n\n                $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';\n\n                return $a;\n            } catch (\\Error $e) {\n                if ('Object not initialized' !== $e->getMessage()) {\n                    throw $e;\n                }\n\n                $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';\n\n                return $a;\n            }\n        }\n\n        foreach ($map as $key => $accessor) {\n            try {\n                $a[$prefix.$key] = $c->$accessor();\n            } catch (\\Exception $e) {\n            }\n        }\n\n        if ($a[$prefix.'realPath'] ?? false) {\n            $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']);\n        }\n\n        if (isset($a[$prefix.'perms'])) {\n            $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);\n        }\n\n        static $mapDate = ['aTime', 'mTime', 'cTime'];\n        foreach ($mapDate as $key) {\n            if (isset($a[$prefix.$key])) {\n                $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]);\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castFileObject(\\SplFileObject $c, array $a, Stub $stub, bool $isNested)\n    {\n        static $map = [\n            'csvControl' => 'getCsvControl',\n            'flags' => 'getFlags',\n            'maxLineLen' => 'getMaxLineLen',\n            'fstat' => 'fstat',\n            'eof' => 'eof',\n            'key' => 'key',\n        ];\n\n        $prefix = Caster::PREFIX_VIRTUAL;\n\n        foreach ($map as $key => $accessor) {\n            try {\n                $a[$prefix.$key] = $c->$accessor();\n            } catch (\\Exception $e) {\n            }\n        }\n\n        if (isset($a[$prefix.'flags'])) {\n            $flagsArray = [];\n            foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) {\n                if ($a[$prefix.'flags'] & $value) {\n                    $flagsArray[] = $name;\n                }\n            }\n            $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']);\n        }\n\n        if (isset($a[$prefix.'fstat'])) {\n            $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']);\n        }\n\n        return $a;\n    }\n\n    public static function castObjectStorage(\\SplObjectStorage $c, array $a, Stub $stub, bool $isNested)\n    {\n        $storage = [];\n        unset($a[Caster::PREFIX_DYNAMIC.\"\\0gcdata\"]); // Don't hit https://bugs.php.net/65967\n        unset($a[\"\\0SplObjectStorage\\0storage\"]);\n\n        $clone = clone $c;\n        foreach ($clone as $obj) {\n            $storage[] = [\n                'object' => $obj,\n                'info' => $clone->getInfo(),\n             ];\n        }\n\n        $a += [\n            Caster::PREFIX_VIRTUAL.'storage' => $storage,\n        ];\n\n        return $a;\n    }\n\n    public static function castOuterIterator(\\OuterIterator $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator();\n\n        return $a;\n    }\n\n    public static function castWeakReference(\\WeakReference $c, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get();\n\n        return $a;\n    }\n\n    private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array\n    {\n        $prefix = Caster::PREFIX_VIRTUAL;\n        $flags = $c->getFlags();\n\n        if (!($flags & \\ArrayObject::STD_PROP_LIST)) {\n            $c->setFlags(\\ArrayObject::STD_PROP_LIST);\n            $a = Caster::castObject($c, \\get_class($c), method_exists($c, '__debugInfo'), $stub->class);\n            $c->setFlags($flags);\n        }\n        if (\\PHP_VERSION_ID < 70400) {\n            $a[$prefix.'storage'] = $c->getArrayCopy();\n        }\n        $a += [\n            $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \\ArrayObject::STD_PROP_LIST),\n            $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \\ArrayObject::ARRAY_AS_PROPS),\n        ];\n        if ($c instanceof \\ArrayObject) {\n            $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass());\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/StubCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts a caster's Stub.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass StubCaster\n{\n    public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested)\n    {\n        if ($isNested) {\n            $stub->type = $c->type;\n            $stub->class = $c->class;\n            $stub->value = $c->value;\n            $stub->handle = $c->handle;\n            $stub->cut = $c->cut;\n            $stub->attr = $c->attr;\n\n            if (Stub::TYPE_REF === $c->type && !$c->class && \\is_string($c->value) && !preg_match('//u', $c->value)) {\n                $stub->type = Stub::TYPE_STRING;\n                $stub->class = Stub::STRING_BINARY;\n            }\n\n            $a = [];\n        }\n\n        return $a;\n    }\n\n    public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested)\n    {\n        return $isNested ? $c->preservedSubset : $a;\n    }\n\n    public static function cutInternals($obj, array $a, Stub $stub, bool $isNested)\n    {\n        if ($isNested) {\n            $stub->cut += \\count($a);\n\n            return [];\n        }\n\n        return $a;\n    }\n\n    public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested)\n    {\n        if ($isNested) {\n            $stub->class = $c->dumpKeys ? '' : null;\n            $stub->handle = 0;\n            $stub->value = null;\n            $stub->cut = $c->cut;\n            $stub->attr = $c->attr;\n\n            $a = [];\n\n            if ($c->value) {\n                foreach (array_keys($c->value) as $k) {\n                    $keys[] = !isset($k[0]) || \"\\0\" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k;\n                }\n                // Preserve references with array_combine()\n                $a = array_combine($keys, $c->value);\n            }\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/SymfonyCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\Uid\\Ulid;\nuse Symfony\\Component\\Uid\\Uuid;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @final\n */\nclass SymfonyCaster\n{\n    private const REQUEST_GETTERS = [\n        'pathInfo' => 'getPathInfo',\n        'requestUri' => 'getRequestUri',\n        'baseUrl' => 'getBaseUrl',\n        'basePath' => 'getBasePath',\n        'method' => 'getMethod',\n        'format' => 'getRequestFormat',\n    ];\n\n    public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested)\n    {\n        $clone = null;\n\n        foreach (self::REQUEST_GETTERS as $prop => $getter) {\n            $key = Caster::PREFIX_PROTECTED.$prop;\n            if (\\array_key_exists($key, $a) && null === $a[$key]) {\n                if (null === $clone) {\n                    $clone = clone $request;\n                }\n                $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}();\n            }\n        }\n\n        return $a;\n    }\n\n    public static function castHttpClient($client, array $a, Stub $stub, bool $isNested)\n    {\n        $multiKey = sprintf(\"\\0%s\\0multi\", \\get_class($client));\n        if (isset($a[$multiKey])) {\n            $a[$multiKey] = new CutStub($a[$multiKey]);\n        }\n\n        return $a;\n    }\n\n    public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested)\n    {\n        $stub->cut += \\count($a);\n        $a = [];\n\n        foreach ($response->getInfo() as $k => $v) {\n            $a[Caster::PREFIX_VIRTUAL.$k] = $v;\n        }\n\n        return $a;\n    }\n\n    public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $uuid->toBase58();\n        $a[Caster::PREFIX_VIRTUAL.'toBase32'] = $uuid->toBase32();\n\n        // symfony/uid >= 5.3\n        if (method_exists($uuid, 'getDateTime')) {\n            $a[Caster::PREFIX_VIRTUAL.'time'] = $uuid->getDateTime()->format('Y-m-d H:i:s.u \\U\\T\\C');\n        }\n\n        return $a;\n    }\n\n    public static function castUlid(Ulid $ulid, array $a, Stub $stub, bool $isNested)\n    {\n        $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $ulid->toBase58();\n        $a[Caster::PREFIX_VIRTUAL.'toRfc4122'] = $ulid->toRfc4122();\n\n        // symfony/uid >= 5.3\n        if (method_exists($ulid, 'getDateTime')) {\n            $a[Caster::PREFIX_VIRTUAL.'time'] = $ulid->getDateTime()->format('Y-m-d H:i:s.v \\U\\T\\C');\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/TraceStub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace().\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass TraceStub extends Stub\n{\n    public $keepArgs;\n    public $sliceOffset;\n    public $sliceLength;\n    public $numberingOffset;\n\n    public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0)\n    {\n        $this->value = $trace;\n        $this->keepArgs = $keepArgs;\n        $this->sliceOffset = $sliceOffset;\n        $this->sliceLength = $sliceLength;\n        $this->numberingOffset = $numberingOffset;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/UuidCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Ramsey\\Uuid\\UuidInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * @author Grégoire Pineau <lyrixx@lyrixx.info>\n */\nfinal class UuidCaster\n{\n    public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array\n    {\n        $a += [\n            Caster::PREFIX_VIRTUAL.'uuid' => (string) $c,\n        ];\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/XmlReaderCaster.php",
    "content": "<?php\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts XmlReader class to array representation.\n *\n * @author Baptiste Clavié <clavie.b@gmail.com>\n *\n * @final\n */\nclass XmlReaderCaster\n{\n    private const NODE_TYPES = [\n        \\XMLReader::NONE => 'NONE',\n        \\XMLReader::ELEMENT => 'ELEMENT',\n        \\XMLReader::ATTRIBUTE => 'ATTRIBUTE',\n        \\XMLReader::TEXT => 'TEXT',\n        \\XMLReader::CDATA => 'CDATA',\n        \\XMLReader::ENTITY_REF => 'ENTITY_REF',\n        \\XMLReader::ENTITY => 'ENTITY',\n        \\XMLReader::PI => 'PI (Processing Instruction)',\n        \\XMLReader::COMMENT => 'COMMENT',\n        \\XMLReader::DOC => 'DOC',\n        \\XMLReader::DOC_TYPE => 'DOC_TYPE',\n        \\XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT',\n        \\XMLReader::NOTATION => 'NOTATION',\n        \\XMLReader::WHITESPACE => 'WHITESPACE',\n        \\XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',\n        \\XMLReader::END_ELEMENT => 'END_ELEMENT',\n        \\XMLReader::END_ENTITY => 'END_ENTITY',\n        \\XMLReader::XML_DECLARATION => 'XML_DECLARATION',\n    ];\n\n    public static function castXmlReader(\\XMLReader $reader, array $a, Stub $stub, bool $isNested)\n    {\n        try {\n            $properties = [\n                'LOADDTD' => @$reader->getParserProperty(\\XMLReader::LOADDTD),\n                'DEFAULTATTRS' => @$reader->getParserProperty(\\XMLReader::DEFAULTATTRS),\n                'VALIDATE' => @$reader->getParserProperty(\\XMLReader::VALIDATE),\n                'SUBST_ENTITIES' => @$reader->getParserProperty(\\XMLReader::SUBST_ENTITIES),\n            ];\n        } catch (\\Error $e) {\n            $properties = [\n                'LOADDTD' => false,\n                'DEFAULTATTRS' => false,\n                'VALIDATE' => false,\n                'SUBST_ENTITIES' => false,\n            ];\n        }\n\n        $props = Caster::PREFIX_VIRTUAL.'parserProperties';\n        $info = [\n            'localName' => $reader->localName,\n            'prefix' => $reader->prefix,\n            'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType),\n            'depth' => $reader->depth,\n            'isDefault' => $reader->isDefault,\n            'isEmptyElement' => \\XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement,\n            'xmlLang' => $reader->xmlLang,\n            'attributeCount' => $reader->attributeCount,\n            'value' => $reader->value,\n            'namespaceURI' => $reader->namespaceURI,\n            'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI,\n            $props => $properties,\n        ];\n\n        if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) {\n            $info[$props] = new EnumStub($info[$props]);\n            $info[$props]->cut = $count;\n        }\n\n        $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count);\n        // +2 because hasValue and hasAttributes are always filtered\n        $stub->cut += $count + 2;\n\n        return $a + $info;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Caster/XmlResourceCaster.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Caster;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * Casts XML resources to array representation.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n *\n * @final\n */\nclass XmlResourceCaster\n{\n    private const XML_ERRORS = [\n        \\XML_ERROR_NONE => 'XML_ERROR_NONE',\n        \\XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY',\n        \\XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX',\n        \\XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS',\n        \\XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN',\n        \\XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN',\n        \\XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR',\n        \\XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH',\n        \\XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE',\n        \\XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT',\n        \\XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF',\n        \\XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY',\n        \\XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF',\n        \\XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY',\n        \\XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF',\n        \\XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF',\n        \\XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF',\n        \\XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI',\n        \\XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING',\n        \\XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING',\n        \\XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION',\n        \\XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING',\n    ];\n\n    public static function castXml($h, array $a, Stub $stub, bool $isNested)\n    {\n        $a['current_byte_index'] = xml_get_current_byte_index($h);\n        $a['current_column_number'] = xml_get_current_column_number($h);\n        $a['current_line_number'] = xml_get_current_line_number($h);\n        $a['error_code'] = xml_get_error_code($h);\n\n        if (isset(self::XML_ERRORS[$a['error_code']])) {\n            $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']);\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/AbstractCloner.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException;\n\n/**\n * AbstractCloner implements a generic caster mechanism for objects and resources.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nabstract class AbstractCloner implements ClonerInterface\n{\n    public static $defaultCasters = [\n        '__PHP_Incomplete_Class' => ['Symfony\\Component\\VarDumper\\Caster\\Caster', 'castPhpIncompleteClass'],\n\n        'Symfony\\Component\\VarDumper\\Caster\\CutStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castStub'],\n        'Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castCutArray'],\n        'Symfony\\Component\\VarDumper\\Caster\\ConstStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castStub'],\n        'Symfony\\Component\\VarDumper\\Caster\\EnumStub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'castEnum'],\n\n        'Fiber' => ['Symfony\\Component\\VarDumper\\Caster\\FiberCaster', 'castFiber'],\n\n        'Closure' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castClosure'],\n        'Generator' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castGenerator'],\n        'ReflectionType' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castType'],\n        'ReflectionAttribute' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castAttribute'],\n        'ReflectionGenerator' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castReflectionGenerator'],\n        'ReflectionClass' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castClass'],\n        'ReflectionClassConstant' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castClassConstant'],\n        'ReflectionFunctionAbstract' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castFunctionAbstract'],\n        'ReflectionMethod' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castMethod'],\n        'ReflectionParameter' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castParameter'],\n        'ReflectionProperty' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castProperty'],\n        'ReflectionReference' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castReference'],\n        'ReflectionExtension' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castExtension'],\n        'ReflectionZendExtension' => ['Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster', 'castZendExtension'],\n\n        'Doctrine\\Common\\Persistence\\ObjectManager' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Doctrine\\Common\\Proxy\\Proxy' => ['Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster', 'castCommonProxy'],\n        'Doctrine\\ORM\\Proxy\\Proxy' => ['Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster', 'castOrmProxy'],\n        'Doctrine\\ORM\\PersistentCollection' => ['Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster', 'castPersistentCollection'],\n        'Doctrine\\Persistence\\ObjectManager' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n\n        'DOMException' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castException'],\n        'DOMStringList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castLength'],\n        'DOMNameList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castLength'],\n        'DOMImplementation' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castImplementation'],\n        'DOMImplementationList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castLength'],\n        'DOMNode' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castNode'],\n        'DOMNameSpaceNode' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castNameSpaceNode'],\n        'DOMDocument' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDocument'],\n        'DOMNodeList' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castLength'],\n        'DOMNamedNodeMap' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castLength'],\n        'DOMCharacterData' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castCharacterData'],\n        'DOMAttr' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castAttr'],\n        'DOMElement' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castElement'],\n        'DOMText' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castText'],\n        'DOMTypeinfo' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castTypeinfo'],\n        'DOMDomError' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDomError'],\n        'DOMLocator' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castLocator'],\n        'DOMDocumentType' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castDocumentType'],\n        'DOMNotation' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castNotation'],\n        'DOMEntity' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castEntity'],\n        'DOMProcessingInstruction' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castProcessingInstruction'],\n        'DOMXPath' => ['Symfony\\Component\\VarDumper\\Caster\\DOMCaster', 'castXPath'],\n\n        'XMLReader' => ['Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster', 'castXmlReader'],\n\n        'ErrorException' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castErrorException'],\n        'Exception' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castException'],\n        'Error' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castError'],\n        'Symfony\\Bridge\\Monolog\\Logger' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\DependencyInjection\\ContainerInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\HttpClient\\AmpHttpClient' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClient'],\n        'Symfony\\Component\\HttpClient\\CurlHttpClient' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClient'],\n        'Symfony\\Component\\HttpClient\\NativeHttpClient' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClient'],\n        'Symfony\\Component\\HttpClient\\Response\\AmpResponse' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpClient\\Response\\CurlResponse' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpClient\\Response\\NativeResponse' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castHttpClientResponse'],\n        'Symfony\\Component\\HttpFoundation\\Request' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castRequest'],\n        'Symfony\\Component\\Uid\\Ulid' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castUlid'],\n        'Symfony\\Component\\Uid\\Uuid' => ['Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster', 'castUuid'],\n        'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castThrowingCasterException'],\n        'Symfony\\Component\\VarDumper\\Caster\\TraceStub' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castTraceStub'],\n        'Symfony\\Component\\VarDumper\\Caster\\FrameStub' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castFrameStub'],\n        'Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => ['Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster', 'castSilencedErrorContext'],\n\n        'Imagine\\Image\\ImageInterface' => ['Symfony\\Component\\VarDumper\\Caster\\ImagineCaster', 'castImage'],\n\n        'Ramsey\\Uuid\\UuidInterface' => ['Symfony\\Component\\VarDumper\\Caster\\UuidCaster', 'castRamseyUuid'],\n\n        'ProxyManager\\Proxy\\ProxyInterface' => ['Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster', 'castProxy'],\n        'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'PHPUnit\\Framework\\MockObject\\MockObject' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'PHPUnit\\Framework\\MockObject\\Stub' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Prophecy\\Prophecy\\ProphecySubjectInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n        'Mockery\\MockInterface' => ['Symfony\\Component\\VarDumper\\Caster\\StubCaster', 'cutInternals'],\n\n        'PDO' => ['Symfony\\Component\\VarDumper\\Caster\\PdoCaster', 'castPdo'],\n        'PDOStatement' => ['Symfony\\Component\\VarDumper\\Caster\\PdoCaster', 'castPdoStatement'],\n\n        'AMQPConnection' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castConnection'],\n        'AMQPChannel' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castChannel'],\n        'AMQPQueue' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castQueue'],\n        'AMQPExchange' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castExchange'],\n        'AMQPEnvelope' => ['Symfony\\Component\\VarDumper\\Caster\\AmqpCaster', 'castEnvelope'],\n\n        'ArrayObject' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castArrayObject'],\n        'ArrayIterator' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castArrayIterator'],\n        'SplDoublyLinkedList' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castDoublyLinkedList'],\n        'SplFileInfo' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castFileInfo'],\n        'SplFileObject' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castFileObject'],\n        'SplHeap' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castHeap'],\n        'SplObjectStorage' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castObjectStorage'],\n        'SplPriorityQueue' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castHeap'],\n        'OuterIterator' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castOuterIterator'],\n        'WeakReference' => ['Symfony\\Component\\VarDumper\\Caster\\SplCaster', 'castWeakReference'],\n\n        'Redis' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedis'],\n        'RedisArray' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedisArray'],\n        'RedisCluster' => ['Symfony\\Component\\VarDumper\\Caster\\RedisCaster', 'castRedisCluster'],\n\n        'DateTimeInterface' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castDateTime'],\n        'DateInterval' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castInterval'],\n        'DateTimeZone' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castTimeZone'],\n        'DatePeriod' => ['Symfony\\Component\\VarDumper\\Caster\\DateCaster', 'castPeriod'],\n\n        'GMP' => ['Symfony\\Component\\VarDumper\\Caster\\GmpCaster', 'castGmp'],\n\n        'MessageFormatter' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castMessageFormatter'],\n        'NumberFormatter' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castNumberFormatter'],\n        'IntlTimeZone' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castIntlTimeZone'],\n        'IntlCalendar' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castIntlCalendar'],\n        'IntlDateFormatter' => ['Symfony\\Component\\VarDumper\\Caster\\IntlCaster', 'castIntlDateFormatter'],\n\n        'Memcached' => ['Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster', 'castMemcached'],\n\n        'Ds\\Collection' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castCollection'],\n        'Ds\\Map' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castMap'],\n        'Ds\\Pair' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castPair'],\n        'Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => ['Symfony\\Component\\VarDumper\\Caster\\DsCaster', 'castPairStub'],\n\n        'mysqli_driver' => ['Symfony\\Component\\VarDumper\\Caster\\MysqliCaster', 'castMysqliDriver'],\n\n        'CurlHandle' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castCurl'],\n        ':curl' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castCurl'],\n\n        ':dba' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castDba'],\n        ':dba persistent' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castDba'],\n\n        'GdImage' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castGd'],\n        ':gd' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castGd'],\n\n        ':mysql link' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castMysqlLink'],\n        ':pgsql large object' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castLargeObject'],\n        ':pgsql link' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castLink'],\n        ':pgsql link persistent' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castLink'],\n        ':pgsql result' => ['Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster', 'castResult'],\n        ':process' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castProcess'],\n        ':stream' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castStream'],\n\n        'OpenSSLCertificate' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castOpensslX509'],\n        ':OpenSSL X.509' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castOpensslX509'],\n\n        ':persistent stream' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castStream'],\n        ':stream-context' => ['Symfony\\Component\\VarDumper\\Caster\\ResourceCaster', 'castStreamContext'],\n\n        'XmlParser' => ['Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster', 'castXml'],\n        ':xml' => ['Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster', 'castXml'],\n\n        'RdKafka' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castRdKafka'],\n        'RdKafka\\Conf' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castConf'],\n        'RdKafka\\KafkaConsumer' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castKafkaConsumer'],\n        'RdKafka\\Metadata\\Broker' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castBrokerMetadata'],\n        'RdKafka\\Metadata\\Collection' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castCollectionMetadata'],\n        'RdKafka\\Metadata\\Partition' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castPartitionMetadata'],\n        'RdKafka\\Metadata\\Topic' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopicMetadata'],\n        'RdKafka\\Message' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castMessage'],\n        'RdKafka\\Topic' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopic'],\n        'RdKafka\\TopicPartition' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopicPartition'],\n        'RdKafka\\TopicConf' => ['Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster', 'castTopicConf'],\n    ];\n\n    protected $maxItems = 2500;\n    protected $maxString = -1;\n    protected $minDepth = 1;\n\n    /**\n     * @var array<string, list<callable>>\n     */\n    private $casters = [];\n\n    /**\n     * @var callable|null\n     */\n    private $prevErrorHandler;\n\n    private $classInfo = [];\n    private $filter = 0;\n\n    /**\n     * @param callable[]|null $casters A map of casters\n     *\n     * @see addCasters\n     */\n    public function __construct(array $casters = null)\n    {\n        if (null === $casters) {\n            $casters = static::$defaultCasters;\n        }\n        $this->addCasters($casters);\n    }\n\n    /**\n     * Adds casters for resources and objects.\n     *\n     * Maps resources or objects types to a callback.\n     * Types are in the key, with a callable caster for value.\n     * Resource types are to be prefixed with a `:`,\n     * see e.g. static::$defaultCasters.\n     *\n     * @param callable[] $casters A map of casters\n     */\n    public function addCasters(array $casters)\n    {\n        foreach ($casters as $type => $callback) {\n            $this->casters[$type][] = $callback;\n        }\n    }\n\n    /**\n     * Sets the maximum number of items to clone past the minimum depth in nested structures.\n     */\n    public function setMaxItems(int $maxItems)\n    {\n        $this->maxItems = $maxItems;\n    }\n\n    /**\n     * Sets the maximum cloned length for strings.\n     */\n    public function setMaxString(int $maxString)\n    {\n        $this->maxString = $maxString;\n    }\n\n    /**\n     * Sets the minimum tree depth where we are guaranteed to clone all the items.  After this\n     * depth is reached, only setMaxItems items will be cloned.\n     */\n    public function setMinDepth(int $minDepth)\n    {\n        $this->minDepth = $minDepth;\n    }\n\n    /**\n     * Clones a PHP variable.\n     *\n     * @param mixed $var    Any PHP variable\n     * @param int   $filter A bit field of Caster::EXCLUDE_* constants\n     *\n     * @return Data\n     */\n    public function cloneVar($var, int $filter = 0)\n    {\n        $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) {\n            if (\\E_RECOVERABLE_ERROR === $type || \\E_USER_ERROR === $type) {\n                // Cloner never dies\n                throw new \\ErrorException($msg, 0, $type, $file, $line);\n            }\n\n            if ($this->prevErrorHandler) {\n                return ($this->prevErrorHandler)($type, $msg, $file, $line, $context);\n            }\n\n            return false;\n        });\n        $this->filter = $filter;\n\n        if ($gc = gc_enabled()) {\n            gc_disable();\n        }\n        try {\n            return new Data($this->doClone($var));\n        } finally {\n            if ($gc) {\n                gc_enable();\n            }\n            restore_error_handler();\n            $this->prevErrorHandler = null;\n        }\n    }\n\n    /**\n     * Effectively clones the PHP variable.\n     *\n     * @param mixed $var Any PHP variable\n     *\n     * @return array\n     */\n    abstract protected function doClone($var);\n\n    /**\n     * Casts an object to an array representation.\n     *\n     * @param bool $isNested True if the object is nested in the dumped structure\n     *\n     * @return array\n     */\n    protected function castObject(Stub $stub, bool $isNested)\n    {\n        $obj = $stub->value;\n        $class = $stub->class;\n\n        if (\\PHP_VERSION_ID < 80000 ? \"\\0\" === ($class[15] ?? null) : str_contains($class, \"@anonymous\\0\")) {\n            $stub->class = get_debug_type($obj);\n        }\n        if (isset($this->classInfo[$class])) {\n            [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class];\n        } else {\n            $i = 2;\n            $parents = [$class];\n            $hasDebugInfo = method_exists($class, '__debugInfo');\n\n            foreach (class_parents($class) as $p) {\n                $parents[] = $p;\n                ++$i;\n            }\n            foreach (class_implements($class) as $p) {\n                $parents[] = $p;\n                ++$i;\n            }\n            $parents[] = '*';\n\n            $r = new \\ReflectionClass($class);\n            $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [\n                'file' => $r->getFileName(),\n                'line' => $r->getStartLine(),\n            ];\n\n            $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo];\n        }\n\n        $stub->attr += $fileInfo;\n        $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class);\n\n        try {\n            while ($i--) {\n                if (!empty($this->casters[$p = $parents[$i]])) {\n                    foreach ($this->casters[$p] as $callback) {\n                        $a = $callback($obj, $a, $stub, $isNested, $this->filter);\n                    }\n                }\n            }\n        } catch (\\Exception $e) {\n            $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;\n        }\n\n        return $a;\n    }\n\n    /**\n     * Casts a resource to an array representation.\n     *\n     * @param bool $isNested True if the object is nested in the dumped structure\n     *\n     * @return array\n     */\n    protected function castResource(Stub $stub, bool $isNested)\n    {\n        $a = [];\n        $res = $stub->value;\n        $type = $stub->class;\n\n        try {\n            if (!empty($this->casters[':'.$type])) {\n                foreach ($this->casters[':'.$type] as $callback) {\n                    $a = $callback($res, $a, $stub, $isNested, $this->filter);\n                }\n            }\n        } catch (\\Exception $e) {\n            $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;\n        }\n\n        return $a;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/ClonerInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\ninterface ClonerInterface\n{\n    /**\n     * Clones a PHP variable.\n     *\n     * @param mixed $var Any PHP variable\n     *\n     * @return Data\n     */\n    public function cloneVar($var);\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/Cursor.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * Represents the current state of a dumper while dumping.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass Cursor\n{\n    public const HASH_INDEXED = Stub::ARRAY_INDEXED;\n    public const HASH_ASSOC = Stub::ARRAY_ASSOC;\n    public const HASH_OBJECT = Stub::TYPE_OBJECT;\n    public const HASH_RESOURCE = Stub::TYPE_RESOURCE;\n\n    public $depth = 0;\n    public $refIndex = 0;\n    public $softRefTo = 0;\n    public $softRefCount = 0;\n    public $softRefHandle = 0;\n    public $hardRefTo = 0;\n    public $hardRefCount = 0;\n    public $hardRefHandle = 0;\n    public $hashType;\n    public $hashKey;\n    public $hashKeyIsBinary;\n    public $hashIndex = 0;\n    public $hashLength = 0;\n    public $hashCut = 0;\n    public $stop = false;\n    public $attr = [];\n    public $skipChildren = false;\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/Data.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\nuse Symfony\\Component\\VarDumper\\Caster\\Caster;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass Data implements \\ArrayAccess, \\Countable, \\IteratorAggregate\n{\n    private $data;\n    private $position = 0;\n    private $key = 0;\n    private $maxDepth = 20;\n    private $maxItemsPerDepth = -1;\n    private $useRefHandles = -1;\n    private $context = [];\n\n    /**\n     * @param array $data An array as returned by ClonerInterface::cloneVar()\n     */\n    public function __construct(array $data)\n    {\n        $this->data = $data;\n    }\n\n    /**\n     * @return string|null\n     */\n    public function getType()\n    {\n        $item = $this->data[$this->position][$this->key];\n\n        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {\n            $item = $item->value;\n        }\n        if (!$item instanceof Stub) {\n            return \\gettype($item);\n        }\n        if (Stub::TYPE_STRING === $item->type) {\n            return 'string';\n        }\n        if (Stub::TYPE_ARRAY === $item->type) {\n            return 'array';\n        }\n        if (Stub::TYPE_OBJECT === $item->type) {\n            return $item->class;\n        }\n        if (Stub::TYPE_RESOURCE === $item->type) {\n            return $item->class.' resource';\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns a native representation of the original value.\n     *\n     * @param array|bool $recursive Whether values should be resolved recursively or not\n     *\n     * @return string|int|float|bool|array|Data[]|null\n     */\n    public function getValue($recursive = false)\n    {\n        $item = $this->data[$this->position][$this->key];\n\n        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {\n            $item = $item->value;\n        }\n        if (!($item = $this->getStub($item)) instanceof Stub) {\n            return $item;\n        }\n        if (Stub::TYPE_STRING === $item->type) {\n            return $item->value;\n        }\n\n        $children = $item->position ? $this->data[$item->position] : [];\n\n        foreach ($children as $k => $v) {\n            if ($recursive && !($v = $this->getStub($v)) instanceof Stub) {\n                continue;\n            }\n            $children[$k] = clone $this;\n            $children[$k]->key = $k;\n            $children[$k]->position = $item->position;\n\n            if ($recursive) {\n                if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) {\n                    $recursive = (array) $recursive;\n                    if (isset($recursive[$v->position])) {\n                        continue;\n                    }\n                    $recursive[$v->position] = true;\n                }\n                $children[$k] = $children[$k]->getValue($recursive);\n            }\n        }\n\n        return $children;\n    }\n\n    /**\n     * @return int\n     */\n    #[\\ReturnTypeWillChange]\n    public function count()\n    {\n        return \\count($this->getValue());\n    }\n\n    /**\n     * @return \\Traversable\n     */\n    #[\\ReturnTypeWillChange]\n    public function getIterator()\n    {\n        if (!\\is_array($value = $this->getValue())) {\n            throw new \\LogicException(sprintf('\"%s\" object holds non-iterable type \"%s\".', self::class, get_debug_type($value)));\n        }\n\n        yield from $value;\n    }\n\n    public function __get(string $key)\n    {\n        if (null !== $data = $this->seek($key)) {\n            $item = $this->getStub($data->data[$data->position][$data->key]);\n\n            return $item instanceof Stub || [] === $item ? $data : $item;\n        }\n\n        return null;\n    }\n\n    /**\n     * @return bool\n     */\n    public function __isset(string $key)\n    {\n        return null !== $this->seek($key);\n    }\n\n    /**\n     * @return bool\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetExists($key)\n    {\n        return $this->__isset($key);\n    }\n\n    /**\n     * @return mixed\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetGet($key)\n    {\n        return $this->__get($key);\n    }\n\n    /**\n     * @return void\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetSet($key, $value)\n    {\n        throw new \\BadMethodCallException(self::class.' objects are immutable.');\n    }\n\n    /**\n     * @return void\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetUnset($key)\n    {\n        throw new \\BadMethodCallException(self::class.' objects are immutable.');\n    }\n\n    /**\n     * @return string\n     */\n    public function __toString()\n    {\n        $value = $this->getValue();\n\n        if (!\\is_array($value)) {\n            return (string) $value;\n        }\n\n        return sprintf('%s (count=%d)', $this->getType(), \\count($value));\n    }\n\n    /**\n     * Returns a depth limited clone of $this.\n     *\n     * @return static\n     */\n    public function withMaxDepth(int $maxDepth)\n    {\n        $data = clone $this;\n        $data->maxDepth = $maxDepth;\n\n        return $data;\n    }\n\n    /**\n     * Limits the number of elements per depth level.\n     *\n     * @return static\n     */\n    public function withMaxItemsPerDepth(int $maxItemsPerDepth)\n    {\n        $data = clone $this;\n        $data->maxItemsPerDepth = $maxItemsPerDepth;\n\n        return $data;\n    }\n\n    /**\n     * Enables/disables objects' identifiers tracking.\n     *\n     * @param bool $useRefHandles False to hide global ref. handles\n     *\n     * @return static\n     */\n    public function withRefHandles(bool $useRefHandles)\n    {\n        $data = clone $this;\n        $data->useRefHandles = $useRefHandles ? -1 : 0;\n\n        return $data;\n    }\n\n    /**\n     * @return static\n     */\n    public function withContext(array $context)\n    {\n        $data = clone $this;\n        $data->context = $context;\n\n        return $data;\n    }\n\n    /**\n     * Seeks to a specific key in nested data structures.\n     *\n     * @param string|int $key The key to seek to\n     *\n     * @return static|null\n     */\n    public function seek($key)\n    {\n        $item = $this->data[$this->position][$this->key];\n\n        if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {\n            $item = $item->value;\n        }\n        if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) {\n            return null;\n        }\n        $keys = [$key];\n\n        switch ($item->type) {\n            case Stub::TYPE_OBJECT:\n                $keys[] = Caster::PREFIX_DYNAMIC.$key;\n                $keys[] = Caster::PREFIX_PROTECTED.$key;\n                $keys[] = Caster::PREFIX_VIRTUAL.$key;\n                $keys[] = \"\\0$item->class\\0$key\";\n                // no break\n            case Stub::TYPE_ARRAY:\n            case Stub::TYPE_RESOURCE:\n                break;\n            default:\n                return null;\n        }\n\n        $data = null;\n        $children = $this->data[$item->position];\n\n        foreach ($keys as $key) {\n            if (isset($children[$key]) || \\array_key_exists($key, $children)) {\n                $data = clone $this;\n                $data->key = $key;\n                $data->position = $item->position;\n                break;\n            }\n        }\n\n        return $data;\n    }\n\n    /**\n     * Dumps data with a DumperInterface dumper.\n     */\n    public function dump(DumperInterface $dumper)\n    {\n        $refs = [0];\n        $cursor = new Cursor();\n\n        if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) {\n            $cursor->attr['if_links'] = true;\n            $cursor->hashType = -1;\n            $dumper->dumpScalar($cursor, 'default', '^');\n            $cursor->attr = ['if_links' => true];\n            $dumper->dumpScalar($cursor, 'default', ' ');\n            $cursor->hashType = 0;\n        }\n\n        $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]);\n    }\n\n    /**\n     * Depth-first dumping of items.\n     *\n     * @param mixed $item A Stub object or the original value being dumped\n     */\n    private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item)\n    {\n        $cursor->refIndex = 0;\n        $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0;\n        $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0;\n        $firstSeen = true;\n\n        if (!$item instanceof Stub) {\n            $cursor->attr = [];\n            $type = \\gettype($item);\n            if ($item && 'array' === $type) {\n                $item = $this->getStub($item);\n            }\n        } elseif (Stub::TYPE_REF === $item->type) {\n            if ($item->handle) {\n                if (!isset($refs[$r = $item->handle - (\\PHP_INT_MAX >> 1)])) {\n                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];\n                } else {\n                    $firstSeen = false;\n                }\n                $cursor->hardRefTo = $refs[$r];\n                $cursor->hardRefHandle = $this->useRefHandles & $item->handle;\n                $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0;\n            }\n            $cursor->attr = $item->attr;\n            $type = $item->class ?: \\gettype($item->value);\n            $item = $this->getStub($item->value);\n        }\n        if ($item instanceof Stub) {\n            if ($item->refCount) {\n                if (!isset($refs[$r = $item->handle])) {\n                    $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];\n                } else {\n                    $firstSeen = false;\n                }\n                $cursor->softRefTo = $refs[$r];\n            }\n            $cursor->softRefHandle = $this->useRefHandles & $item->handle;\n            $cursor->softRefCount = $item->refCount;\n            $cursor->attr = $item->attr;\n            $cut = $item->cut;\n\n            if ($item->position && $firstSeen) {\n                $children = $this->data[$item->position];\n\n                if ($cursor->stop) {\n                    if ($cut >= 0) {\n                        $cut += \\count($children);\n                    }\n                    $children = [];\n                }\n            } else {\n                $children = [];\n            }\n            switch ($item->type) {\n                case Stub::TYPE_STRING:\n                    $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut);\n                    break;\n\n                case Stub::TYPE_ARRAY:\n                    $item = clone $item;\n                    $item->type = $item->class;\n                    $item->class = $item->value;\n                    // no break\n                case Stub::TYPE_OBJECT:\n                case Stub::TYPE_RESOURCE:\n                    $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;\n                    $dumper->enterHash($cursor, $item->type, $item->class, $withChildren);\n                    if ($withChildren) {\n                        if ($cursor->skipChildren) {\n                            $withChildren = false;\n                            $cut = -1;\n                        } else {\n                            $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);\n                        }\n                    } elseif ($children && 0 <= $cut) {\n                        $cut += \\count($children);\n                    }\n                    $cursor->skipChildren = false;\n                    $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);\n                    break;\n\n                default:\n                    throw new \\RuntimeException(sprintf('Unexpected Stub type: \"%s\".', $item->type));\n            }\n        } elseif ('array' === $type) {\n            $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false);\n            $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0);\n        } elseif ('string' === $type) {\n            $dumper->dumpString($cursor, $item, false, 0);\n        } else {\n            $dumper->dumpScalar($cursor, $type, $item);\n        }\n    }\n\n    /**\n     * Dumps children of hash structures.\n     *\n     * @return int The final number of removed items\n     */\n    private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int\n    {\n        $cursor = clone $parentCursor;\n        ++$cursor->depth;\n        $cursor->hashType = $hashType;\n        $cursor->hashIndex = 0;\n        $cursor->hashLength = \\count($children);\n        $cursor->hashCut = $hashCut;\n        foreach ($children as $key => $child) {\n            $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);\n            $cursor->hashKey = $dumpKeys ? $key : null;\n            $this->dumpItem($dumper, $cursor, $refs, $child);\n            if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {\n                $parentCursor->stop = true;\n\n                return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut;\n            }\n        }\n\n        return $hashCut;\n    }\n\n    private function getStub($item)\n    {\n        if (!$item || !\\is_array($item)) {\n            return $item;\n        }\n\n        $stub = new Stub();\n        $stub->type = Stub::TYPE_ARRAY;\n        foreach ($item as $stub->class => $stub->position) {\n        }\n        if (isset($item[0])) {\n            $stub->cut = $item[0];\n        }\n        $stub->value = $stub->cut + ($stub->position ? \\count($this->data[$stub->position]) : 0);\n\n        return $stub;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/DumperInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * DumperInterface used by Data objects.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\ninterface DumperInterface\n{\n    /**\n     * Dumps a scalar value.\n     *\n     * @param string                $type  The PHP type of the value being dumped\n     * @param string|int|float|bool $value The scalar value being dumped\n     */\n    public function dumpScalar(Cursor $cursor, string $type, $value);\n\n    /**\n     * Dumps a string.\n     *\n     * @param string $str The string being dumped\n     * @param bool   $bin Whether $str is UTF-8 or binary encoded\n     * @param int    $cut The number of characters $str has been cut by\n     */\n    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut);\n\n    /**\n     * Dumps while entering an hash.\n     *\n     * @param int        $type     A Cursor::HASH_* const for the type of hash\n     * @param string|int $class    The object class, resource type or array count\n     * @param bool       $hasChild When the dump of the hash has child item\n     */\n    public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild);\n\n    /**\n     * Dumps while leaving an hash.\n     *\n     * @param int        $type     A Cursor::HASH_* const for the type of hash\n     * @param string|int $class    The object class, resource type or array count\n     * @param bool       $hasChild When the dump of the hash has child item\n     * @param int        $cut      The number of items the hash has been cut by\n     */\n    public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut);\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/Stub.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * Represents the main properties of a PHP variable.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass Stub\n{\n    public const TYPE_REF = 1;\n    public const TYPE_STRING = 2;\n    public const TYPE_ARRAY = 3;\n    public const TYPE_OBJECT = 4;\n    public const TYPE_RESOURCE = 5;\n\n    public const STRING_BINARY = 1;\n    public const STRING_UTF8 = 2;\n\n    public const ARRAY_ASSOC = 1;\n    public const ARRAY_INDEXED = 2;\n\n    public $type = self::TYPE_REF;\n    public $class = '';\n    public $value;\n    public $cut = 0;\n    public $handle = 0;\n    public $refCount = 0;\n    public $position = 0;\n    public $attr = [];\n\n    private static $defaultProperties = [];\n\n    /**\n     * @internal\n     */\n    public function __sleep(): array\n    {\n        $properties = [];\n\n        if (!isset(self::$defaultProperties[$c = static::class])) {\n            self::$defaultProperties[$c] = get_class_vars($c);\n\n            foreach ((new \\ReflectionClass($c))->getStaticProperties() as $k => $v) {\n                unset(self::$defaultProperties[$c][$k]);\n            }\n        }\n\n        foreach (self::$defaultProperties[$c] as $k => $v) {\n            if ($this->$k !== $v) {\n                $properties[] = $k;\n            }\n        }\n\n        return $properties;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Cloner/VarCloner.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Cloner;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass VarCloner extends AbstractCloner\n{\n    private static $gid;\n    private static $arrayCache = [];\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doClone($var)\n    {\n        $len = 1;                       // Length of $queue\n        $pos = 0;                       // Number of cloned items past the minimum depth\n        $refsCounter = 0;               // Hard references counter\n        $queue = [[$var]];              // This breadth-first queue is the return value\n        $hardRefs = [];                 // Map of original zval ids to stub objects\n        $objRefs = [];                  // Map of original object handles to their stub object counterpart\n        $objects = [];                  // Keep a ref to objects to ensure their handle cannot be reused while cloning\n        $resRefs = [];                  // Map of original resource handles to their stub object counterpart\n        $values = [];                   // Map of stub objects' ids to original values\n        $maxItems = $this->maxItems;\n        $maxString = $this->maxString;\n        $minDepth = $this->minDepth;\n        $currentDepth = 0;              // Current tree depth\n        $currentDepthFinalIndex = 0;    // Final $queue index for current tree depth\n        $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached\n        $cookie = (object) [];          // Unique object used to detect hard references\n        $a = null;                      // Array cast for nested structures\n        $stub = null;                   // Stub capturing the main properties of an original item value\n                                        // or null if the original value is used directly\n\n        if (!$gid = self::$gid) {\n            $gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable\n        }\n        $arrayStub = new Stub();\n        $arrayStub->type = Stub::TYPE_ARRAY;\n        $fromObjCast = false;\n\n        for ($i = 0; $i < $len; ++$i) {\n            // Detect when we move on to the next tree depth\n            if ($i > $currentDepthFinalIndex) {\n                ++$currentDepth;\n                $currentDepthFinalIndex = $len - 1;\n                if ($currentDepth >= $minDepth) {\n                    $minimumDepthReached = true;\n                }\n            }\n\n            $refs = $vals = $queue[$i];\n            foreach ($vals as $k => $v) {\n                // $v is the original value or a stub object in case of hard references\n\n                if (\\PHP_VERSION_ID >= 70400) {\n                    $zvalRef = ($r = \\ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;\n                } else {\n                    $refs[$k] = $cookie;\n                    $zvalRef = $vals[$k] === $cookie;\n                }\n\n                if ($zvalRef) {\n                    $vals[$k] = &$stub;         // Break hard references to make $queue completely\n                    unset($stub);               // independent from the original structure\n                    if (\\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) {\n                        if (\\PHP_VERSION_ID >= 70400) {\n                            $v = $vals[$k];\n                        } else {\n                            $refs[$k] = $vals[$k] = $v;\n                        }\n                        if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {\n                            ++$v->value->refCount;\n                        }\n                        ++$v->refCount;\n                        continue;\n                    }\n                    $vals[$k] = new Stub();\n                    $vals[$k]->value = $v;\n                    $vals[$k]->handle = ++$refsCounter;\n\n                    if (\\PHP_VERSION_ID >= 70400) {\n                        $hardRefs[$zvalRef] = $vals[$k];\n                    } else {\n                        $refs[$k] = $vals[$k];\n                        $h = spl_object_id($refs[$k]);\n                        $hardRefs[$h] = &$refs[$k];\n                        $values[$h] = $v;\n                    }\n                }\n                // Create $stub when the original value $v cannot be used directly\n                // If $v is a nested structure, put that structure in array $a\n                switch (true) {\n                    case null === $v:\n                    case \\is_bool($v):\n                    case \\is_int($v):\n                    case \\is_float($v):\n                        continue 2;\n                    case \\is_string($v):\n                        if ('' === $v) {\n                            continue 2;\n                        }\n                        if (!preg_match('//u', $v)) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_STRING;\n                            $stub->class = Stub::STRING_BINARY;\n                            if (0 <= $maxString && 0 < $cut = \\strlen($v) - $maxString) {\n                                $stub->cut = $cut;\n                                $stub->value = substr($v, 0, -$cut);\n                            } else {\n                                $stub->value = $v;\n                            }\n                        } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_STRING;\n                            $stub->class = Stub::STRING_UTF8;\n                            $stub->cut = $cut;\n                            $stub->value = mb_substr($v, 0, $maxString, 'UTF-8');\n                        } else {\n                            continue 2;\n                        }\n                        $a = null;\n                        break;\n\n                    case \\is_array($v):\n                        if (!$v) {\n                            continue 2;\n                        }\n                        $stub = $arrayStub;\n\n                        if (\\PHP_VERSION_ID >= 80100) {\n                            $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC;\n                            $a = $v;\n                            break;\n                        }\n\n                        $stub->class = Stub::ARRAY_INDEXED;\n\n                        $j = -1;\n                        foreach ($v as $gk => $gv) {\n                            if ($gk !== ++$j) {\n                                $stub->class = Stub::ARRAY_ASSOC;\n                                $a = $v;\n                                $a[$gid] = true;\n                                break;\n                            }\n                        }\n\n                        // Copies of $GLOBALS have very strange behavior,\n                        // let's detect them with some black magic\n                        if (isset($v[$gid])) {\n                            unset($v[$gid]);\n                            $a = [];\n                            foreach ($v as $gk => &$gv) {\n                                if ($v === $gv && (\\PHP_VERSION_ID < 70400 || !isset($hardRefs[\\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) {\n                                    unset($v);\n                                    $v = new Stub();\n                                    $v->value = [$v->cut = \\count($gv), Stub::TYPE_ARRAY => 0];\n                                    $v->handle = -1;\n                                    if (\\PHP_VERSION_ID >= 70400) {\n                                        $gv = &$a[$gk];\n                                        $hardRefs[\\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv;\n                                    } else {\n                                        $gv = &$hardRefs[spl_object_id($v)];\n                                    }\n                                    $gv = $v;\n                                }\n\n                                $a[$gk] = &$gv;\n                            }\n                            unset($gv);\n                        } else {\n                            $a = $v;\n                        }\n                        break;\n\n                    case \\is_object($v):\n                        if (empty($objRefs[$h = spl_object_id($v)])) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_OBJECT;\n                            $stub->class = \\get_class($v);\n                            $stub->value = $v;\n                            $stub->handle = $h;\n                            $a = $this->castObject($stub, 0 < $i);\n                            if ($v !== $stub->value) {\n                                if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {\n                                    break;\n                                }\n                                $stub->handle = $h = spl_object_id($stub->value);\n                            }\n                            $stub->value = null;\n                            if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {\n                                $stub->cut = \\count($a);\n                                $a = null;\n                            }\n                        }\n                        if (empty($objRefs[$h])) {\n                            $objRefs[$h] = $stub;\n                            $objects[] = $v;\n                        } else {\n                            $stub = $objRefs[$h];\n                            ++$stub->refCount;\n                            $a = null;\n                        }\n                        break;\n\n                    default: // resource\n                        if (empty($resRefs[$h = (int) $v])) {\n                            $stub = new Stub();\n                            $stub->type = Stub::TYPE_RESOURCE;\n                            if ('Unknown' === $stub->class = @get_resource_type($v)) {\n                                $stub->class = 'Closed';\n                            }\n                            $stub->value = $v;\n                            $stub->handle = $h;\n                            $a = $this->castResource($stub, 0 < $i);\n                            $stub->value = null;\n                            if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {\n                                $stub->cut = \\count($a);\n                                $a = null;\n                            }\n                        }\n                        if (empty($resRefs[$h])) {\n                            $resRefs[$h] = $stub;\n                        } else {\n                            $stub = $resRefs[$h];\n                            ++$stub->refCount;\n                            $a = null;\n                        }\n                        break;\n                }\n\n                if ($a) {\n                    if (!$minimumDepthReached || 0 > $maxItems) {\n                        $queue[$len] = $a;\n                        $stub->position = $len++;\n                    } elseif ($pos < $maxItems) {\n                        if ($maxItems < $pos += \\count($a)) {\n                            $a = \\array_slice($a, 0, $maxItems - $pos, true);\n                            if ($stub->cut >= 0) {\n                                $stub->cut += $pos - $maxItems;\n                            }\n                        }\n                        $queue[$len] = $a;\n                        $stub->position = $len++;\n                    } elseif ($stub->cut >= 0) {\n                        $stub->cut += \\count($a);\n                        $stub->position = 0;\n                    }\n                }\n\n                if ($arrayStub === $stub) {\n                    if ($arrayStub->cut) {\n                        $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position];\n                        $arrayStub->cut = 0;\n                    } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) {\n                        $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position];\n                    } else {\n                        self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];\n                    }\n                }\n\n                if (!$zvalRef) {\n                    $vals[$k] = $stub;\n                } elseif (\\PHP_VERSION_ID >= 70400) {\n                    $hardRefs[$zvalRef]->value = $stub;\n                } else {\n                    $refs[$k]->value = $stub;\n                }\n            }\n\n            if ($fromObjCast) {\n                $fromObjCast = false;\n                $refs = $vals;\n                $vals = [];\n                $j = -1;\n                foreach ($queue[$i] as $k => $v) {\n                    foreach ([$k => true] as $gk => $gv) {\n                    }\n                    if ($gk !== $k) {\n                        $vals = (object) $vals;\n                        $vals->{$k} = $refs[++$j];\n                        $vals = (array) $vals;\n                    } else {\n                        $vals[$k] = $refs[++$j];\n                    }\n                }\n            }\n\n            $queue[$i] = $vals;\n        }\n\n        foreach ($values as $h => $v) {\n            $hardRefs[$h] = $v;\n        }\n\n        return $queue;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command\\Descriptor;\n\nuse Symfony\\Component\\Console\\Input\\ArrayInput;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\n\n/**\n * Describe collected data clones for cli output.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass CliDescriptor implements DumpDescriptorInterface\n{\n    private $dumper;\n    private $lastIdentifier;\n\n    public function __construct(CliDumper $dumper)\n    {\n        $this->dumper = $dumper;\n    }\n\n    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void\n    {\n        $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output);\n        $this->dumper->setColors($output->isDecorated());\n\n        $rows = [['date', date('r', (int) $context['timestamp'])]];\n        $lastIdentifier = $this->lastIdentifier;\n        $this->lastIdentifier = $clientId;\n\n        $section = \"Received from client #$clientId\";\n        if (isset($context['request'])) {\n            $request = $context['request'];\n            $this->lastIdentifier = $request['identifier'];\n            $section = sprintf('%s %s', $request['method'], $request['uri']);\n            if ($controller = $request['controller']) {\n                $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), \"\\n\")];\n            }\n        } elseif (isset($context['cli'])) {\n            $this->lastIdentifier = $context['cli']['identifier'];\n            $section = '$ '.$context['cli']['command_line'];\n        }\n\n        if ($this->lastIdentifier !== $lastIdentifier) {\n            $io->section($section);\n        }\n\n        if (isset($context['source'])) {\n            $source = $context['source'];\n            $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']);\n            if ($fileLink = $source['file_link'] ?? null) {\n                $sourceInfo = sprintf('<href=%s>%s</>', $fileLink, $sourceInfo);\n            }\n            $rows[] = ['source', $sourceInfo];\n            $file = $source['file_relative'] ?? $source['file'];\n            $rows[] = ['file', $file];\n        }\n\n        $io->table([], $rows);\n\n        $this->dumper->dump($data);\n        $io->newLine();\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command\\Descriptor;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\n\n/**\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\ninterface DumpDescriptorInterface\n{\n    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void;\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command\\Descriptor;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\n\n/**\n * Describe collected data clones for html output.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass HtmlDescriptor implements DumpDescriptorInterface\n{\n    private $dumper;\n    private $initialized = false;\n\n    public function __construct(HtmlDumper $dumper)\n    {\n        $this->dumper = $dumper;\n    }\n\n    public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void\n    {\n        if (!$this->initialized) {\n            $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css');\n            $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js');\n            $output->writeln(\"<style>$styles</style><script>$scripts</script>\");\n            $this->initialized = true;\n        }\n\n        $title = '-';\n        if (isset($context['request'])) {\n            $request = $context['request'];\n            $controller = \"<span class='dumped-tag'>{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}</span>\";\n            $title = sprintf('<code>%s</code> <a href=\"%s\">%s</a>', $request['method'], $uri = $request['uri'], $uri);\n            $dedupIdentifier = $request['identifier'];\n        } elseif (isset($context['cli'])) {\n            $title = '<code>$ </code>'.$context['cli']['command_line'];\n            $dedupIdentifier = $context['cli']['identifier'];\n        } else {\n            $dedupIdentifier = uniqid('', true);\n        }\n\n        $sourceDescription = '';\n        if (isset($context['source'])) {\n            $source = $context['source'];\n            $projectDir = $source['project_dir'] ?? null;\n            $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']);\n            if (isset($source['file_link'])) {\n                $sourceDescription = sprintf('<a href=\"%s\">%s</a>', $source['file_link'], $sourceDescription);\n            }\n        }\n\n        $isoDate = $this->extractDate($context, 'c');\n        $tags = array_filter([\n            'controller' => $controller ?? null,\n            'project dir' => $projectDir ?? null,\n        ]);\n\n        $output->writeln(<<<HTML\n<article data-dedup-id=\"$dedupIdentifier\">\n    <header>\n        <div class=\"row\">\n            <h2 class=\"col\">$title</h2>\n            <time class=\"col text-small\" title=\"$isoDate\" datetime=\"$isoDate\">\n                {$this->extractDate($context)}\n            </time>\n        </div>\n        {$this->renderTags($tags)}\n    </header>\n    <section class=\"body\">\n        <p class=\"text-small\">\n            $sourceDescription\n        </p>\n        {$this->dumper->dump($data, true)}\n    </section>\n</article>\nHTML\n        );\n    }\n\n    private function extractDate(array $context, string $format = 'r'): string\n    {\n        return date($format, (int) $context['timestamp']);\n    }\n\n    private function renderTags(array $tags): string\n    {\n        if (!$tags) {\n            return '';\n        }\n\n        $renderedTags = '';\n        foreach ($tags as $key => $value) {\n            $renderedTags .= sprintf('<li><span class=\"badge\">%s</span>%s</li>', $key, $value);\n        }\n\n        return <<<HTML\n<div class=\"row\">\n    <ul class=\"tags\">\n        $renderedTags\n    </ul>\n</div>\nHTML;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Command/ServerDumpCommand.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Command;\n\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Completion\\CompletionInput;\nuse Symfony\\Component\\Console\\Completion\\CompletionSuggestions;\nuse Symfony\\Component\\Console\\Exception\\InvalidArgumentException;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface;\nuse Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Server\\DumpServer;\n\n/**\n * Starts a dump server to collect and output dumps on a single place with multiple formats support.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass ServerDumpCommand extends Command\n{\n    protected static $defaultName = 'server:dump';\n    protected static $defaultDescription = 'Start a dump server that collects and displays dumps in a single place';\n\n    private $server;\n\n    /** @var DumpDescriptorInterface[] */\n    private $descriptors;\n\n    public function __construct(DumpServer $server, array $descriptors = [])\n    {\n        $this->server = $server;\n        $this->descriptors = $descriptors + [\n            'cli' => new CliDescriptor(new CliDumper()),\n            'html' => new HtmlDescriptor(new HtmlDumper()),\n        ];\n\n        parent::__construct();\n    }\n\n    protected function configure()\n    {\n        $this\n            ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli')\n            ->setDescription(self::$defaultDescription)\n            ->setHelp(<<<'EOF'\n<info>%command.name%</info> starts a dump server that collects and displays\ndumps in a single place for debugging you application:\n\n  <info>php %command.full_name%</info>\n\nYou can consult dumped data in HTML format in your browser by providing the <comment>--format=html</comment> option\nand redirecting the output to a file:\n\n  <info>php %command.full_name% --format=\"html\" > dump.html</info>\n\nEOF\n            )\n        ;\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $io = new SymfonyStyle($input, $output);\n        $format = $input->getOption('format');\n\n        if (!$descriptor = $this->descriptors[$format] ?? null) {\n            throw new InvalidArgumentException(sprintf('Unsupported format \"%s\".', $format));\n        }\n\n        $errorIo = $io->getErrorStyle();\n        $errorIo->title('Symfony Var Dumper Server');\n\n        $this->server->start();\n\n        $errorIo->success(sprintf('Server listening on %s', $this->server->getHost()));\n        $errorIo->comment('Quit the server with CONTROL-C.');\n\n        $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) {\n            $descriptor->describe($io, $data, $context, $clientId);\n        });\n\n        return 0;\n    }\n\n    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void\n    {\n        if ($input->mustSuggestOptionValuesFor('format')) {\n            $suggestions->suggestValues($this->getAvailableFormats());\n        }\n    }\n\n    private function getAvailableFormats(): array\n    {\n        return array_keys($this->descriptors);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/AbstractDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\DumperInterface;\n\n/**\n * Abstract mechanism for dumping a Data object.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nabstract class AbstractDumper implements DataDumperInterface, DumperInterface\n{\n    public const DUMP_LIGHT_ARRAY = 1;\n    public const DUMP_STRING_LENGTH = 2;\n    public const DUMP_COMMA_SEPARATOR = 4;\n    public const DUMP_TRAILING_COMMA = 8;\n\n    public static $defaultOutput = 'php://output';\n\n    protected $line = '';\n    protected $lineDumper;\n    protected $outputStream;\n    protected $decimalPoint; // This is locale dependent\n    protected $indentPad = '  ';\n    protected $flags;\n\n    private $charset = '';\n\n    /**\n     * @param callable|resource|string|null $output  A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput\n     * @param string|null                   $charset The default character encoding to use for non-UTF8 strings\n     * @param int                           $flags   A bit field of static::DUMP_* constants to fine tune dumps representation\n     */\n    public function __construct($output = null, string $charset = null, int $flags = 0)\n    {\n        $this->flags = $flags;\n        $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');\n        $this->decimalPoint = localeconv();\n        $this->decimalPoint = $this->decimalPoint['decimal_point'];\n        $this->setOutput($output ?: static::$defaultOutput);\n        if (!$output && \\is_string(static::$defaultOutput)) {\n            static::$defaultOutput = $this->outputStream;\n        }\n    }\n\n    /**\n     * Sets the output destination of the dumps.\n     *\n     * @param callable|resource|string $output A line dumper callable, an opened stream or an output path\n     *\n     * @return callable|resource|string The previous output destination\n     */\n    public function setOutput($output)\n    {\n        $prev = $this->outputStream ?? $this->lineDumper;\n\n        if (\\is_callable($output)) {\n            $this->outputStream = null;\n            $this->lineDumper = $output;\n        } else {\n            if (\\is_string($output)) {\n                $output = fopen($output, 'w');\n            }\n            $this->outputStream = $output;\n            $this->lineDumper = [$this, 'echoLine'];\n        }\n\n        return $prev;\n    }\n\n    /**\n     * Sets the default character encoding to use for non-UTF8 strings.\n     *\n     * @return string The previous charset\n     */\n    public function setCharset(string $charset)\n    {\n        $prev = $this->charset;\n\n        $charset = strtoupper($charset);\n        $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;\n\n        $this->charset = $charset;\n\n        return $prev;\n    }\n\n    /**\n     * Sets the indentation pad string.\n     *\n     * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level\n     *\n     * @return string The previous indent pad\n     */\n    public function setIndentPad(string $pad)\n    {\n        $prev = $this->indentPad;\n        $this->indentPad = $pad;\n\n        return $prev;\n    }\n\n    /**\n     * Dumps a Data object.\n     *\n     * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump\n     *\n     * @return string|null The dump as string when $output is true\n     */\n    public function dump(Data $data, $output = null)\n    {\n        $this->decimalPoint = localeconv();\n        $this->decimalPoint = $this->decimalPoint['decimal_point'];\n\n        if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\\LC_NUMERIC, 0) : null) {\n            setlocale(\\LC_NUMERIC, 'C');\n        }\n\n        if ($returnDump = true === $output) {\n            $output = fopen('php://memory', 'r+');\n        }\n        if ($output) {\n            $prevOutput = $this->setOutput($output);\n        }\n        try {\n            $data->dump($this);\n            $this->dumpLine(-1);\n\n            if ($returnDump) {\n                $result = stream_get_contents($output, -1, 0);\n                fclose($output);\n\n                return $result;\n            }\n        } finally {\n            if ($output) {\n                $this->setOutput($prevOutput);\n            }\n            if ($locale) {\n                setlocale(\\LC_NUMERIC, $locale);\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Dumps the current line.\n     *\n     * @param int $depth The recursive depth in the dumped structure for the line being dumped,\n     *                   or -1 to signal the end-of-dump to the line dumper callable\n     */\n    protected function dumpLine(int $depth)\n    {\n        ($this->lineDumper)($this->line, $depth, $this->indentPad);\n        $this->line = '';\n    }\n\n    /**\n     * Generic line dumper callback.\n     */\n    protected function echoLine(string $line, int $depth, string $indentPad)\n    {\n        if (-1 !== $depth) {\n            fwrite($this->outputStream, str_repeat($indentPad, $depth).$line.\"\\n\");\n        }\n    }\n\n    /**\n     * Converts a non-UTF-8 string to UTF-8.\n     *\n     * @return string|null\n     */\n    protected function utf8Encode(?string $s)\n    {\n        if (null === $s || preg_match('//u', $s)) {\n            return $s;\n        }\n\n        if (!\\function_exists('iconv')) {\n            throw new \\RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.');\n        }\n\n        if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {\n            return $c;\n        }\n        if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) {\n            return $c;\n        }\n\n        return iconv('CP850', 'UTF-8', $s);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/CliDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Cursor;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * CliDumper dumps variables for command line output.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass CliDumper extends AbstractDumper\n{\n    public static $defaultColors;\n    public static $defaultOutput = 'php://stdout';\n\n    protected $colors;\n    protected $maxStringWidth = 0;\n    protected $styles = [\n        // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\n        'default' => '0;38;5;208',\n        'num' => '1;38;5;38',\n        'const' => '1;38;5;208',\n        'str' => '1;38;5;113',\n        'note' => '38;5;38',\n        'ref' => '38;5;247',\n        'public' => '',\n        'protected' => '',\n        'private' => '',\n        'meta' => '38;5;170',\n        'key' => '38;5;113',\n        'index' => '38;5;38',\n    ];\n\n    protected static $controlCharsRx = '/[\\x00-\\x1F\\x7F]+/';\n    protected static $controlCharsMap = [\n        \"\\t\" => '\\t',\n        \"\\n\" => '\\n',\n        \"\\v\" => '\\v',\n        \"\\f\" => '\\f',\n        \"\\r\" => '\\r',\n        \"\\033\" => '\\e',\n    ];\n\n    protected $collapseNextHash = false;\n    protected $expandNextHash = false;\n\n    private $displayOptions = [\n        'fileLinkFormat' => null,\n    ];\n\n    private $handlesHrefGracefully;\n\n    /**\n     * {@inheritdoc}\n     */\n    public function __construct($output = null, string $charset = null, int $flags = 0)\n    {\n        parent::__construct($output, $charset, $flags);\n\n        if ('\\\\' === \\DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) {\n            // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI\n            $this->setStyles([\n                'default' => '31',\n                'num' => '1;34',\n                'const' => '1;31',\n                'str' => '1;32',\n                'note' => '34',\n                'ref' => '1;30',\n                'meta' => '35',\n                'key' => '32',\n                'index' => '34',\n            ]);\n        }\n\n        $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l';\n    }\n\n    /**\n     * Enables/disables colored output.\n     */\n    public function setColors(bool $colors)\n    {\n        $this->colors = $colors;\n    }\n\n    /**\n     * Sets the maximum number of characters per line for dumped strings.\n     */\n    public function setMaxStringWidth(int $maxStringWidth)\n    {\n        $this->maxStringWidth = $maxStringWidth;\n    }\n\n    /**\n     * Configures styles.\n     *\n     * @param array $styles A map of style names to style definitions\n     */\n    public function setStyles(array $styles)\n    {\n        $this->styles = $styles + $this->styles;\n    }\n\n    /**\n     * Configures display options.\n     *\n     * @param array $displayOptions A map of display options to customize the behavior\n     */\n    public function setDisplayOptions(array $displayOptions)\n    {\n        $this->displayOptions = $displayOptions + $this->displayOptions;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function dumpScalar(Cursor $cursor, string $type, $value)\n    {\n        $this->dumpKey($cursor);\n\n        $style = 'const';\n        $attr = $cursor->attr;\n\n        switch ($type) {\n            case 'default':\n                $style = 'default';\n                break;\n\n            case 'integer':\n                $style = 'num';\n\n                if (isset($this->styles['integer'])) {\n                    $style = 'integer';\n                }\n\n                break;\n\n            case 'double':\n                $style = 'num';\n\n                if (isset($this->styles['float'])) {\n                    $style = 'float';\n                }\n\n                switch (true) {\n                    case \\INF === $value:  $value = 'INF'; break;\n                    case -\\INF === $value: $value = '-INF'; break;\n                    case is_nan($value):  $value = 'NAN'; break;\n                    default:\n                        $value = (string) $value;\n                        if (!str_contains($value, $this->decimalPoint)) {\n                            $value .= $this->decimalPoint.'0';\n                        }\n                        break;\n                }\n                break;\n\n            case 'NULL':\n                $value = 'null';\n                break;\n\n            case 'boolean':\n                $value = $value ? 'true' : 'false';\n                break;\n\n            default:\n                $attr += ['value' => $this->utf8Encode($value)];\n                $value = $this->utf8Encode($type);\n                break;\n        }\n\n        $this->line .= $this->style($style, $value, $attr);\n\n        $this->endValue($cursor);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)\n    {\n        $this->dumpKey($cursor);\n        $attr = $cursor->attr;\n\n        if ($bin) {\n            $str = $this->utf8Encode($str);\n        }\n        if ('' === $str) {\n            $this->line .= '\"\"';\n            $this->endValue($cursor);\n        } else {\n            $attr += [\n                'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,\n                'binary' => $bin,\n            ];\n            $str = $bin && false !== strpos($str, \"\\0\") ? [$str] : explode(\"\\n\", $str);\n            if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) {\n                unset($str[1]);\n                $str[0] .= \"\\n\";\n            }\n            $m = \\count($str) - 1;\n            $i = $lineCut = 0;\n\n            if (self::DUMP_STRING_LENGTH & $this->flags) {\n                $this->line .= '('.$attr['length'].') ';\n            }\n            if ($bin) {\n                $this->line .= 'b';\n            }\n\n            if ($m) {\n                $this->line .= '\"\"\"';\n                $this->dumpLine($cursor->depth);\n            } else {\n                $this->line .= '\"';\n            }\n\n            foreach ($str as $str) {\n                if ($i < $m) {\n                    $str .= \"\\n\";\n                }\n                if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {\n                    $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');\n                    $lineCut = $len - $this->maxStringWidth;\n                }\n                if ($m && 0 < $cursor->depth) {\n                    $this->line .= $this->indentPad;\n                }\n                if ('' !== $str) {\n                    $this->line .= $this->style('str', $str, $attr);\n                }\n                if ($i++ == $m) {\n                    if ($m) {\n                        if ('' !== $str) {\n                            $this->dumpLine($cursor->depth);\n                            if (0 < $cursor->depth) {\n                                $this->line .= $this->indentPad;\n                            }\n                        }\n                        $this->line .= '\"\"\"';\n                    } else {\n                        $this->line .= '\"';\n                    }\n                    if ($cut < 0) {\n                        $this->line .= '…';\n                        $lineCut = 0;\n                    } elseif ($cut) {\n                        $lineCut += $cut;\n                    }\n                }\n                if ($lineCut) {\n                    $this->line .= '…'.$lineCut;\n                    $lineCut = 0;\n                }\n\n                if ($i > $m) {\n                    $this->endValue($cursor);\n                } else {\n                    $this->dumpLine($cursor->depth);\n                }\n            }\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild)\n    {\n        if (null === $this->colors) {\n            $this->colors = $this->supportsColors();\n        }\n\n        $this->dumpKey($cursor);\n        $attr = $cursor->attr;\n\n        if ($this->collapseNextHash) {\n            $cursor->skipChildren = true;\n            $this->collapseNextHash = $hasChild = false;\n        }\n\n        $class = $this->utf8Encode($class);\n        if (Cursor::HASH_OBJECT === $type) {\n            $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{';\n        } elseif (Cursor::HASH_RESOURCE === $type) {\n            $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' ');\n        } else {\n            $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';\n        }\n\n        if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) {\n            $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]);\n        } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) {\n            $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]);\n        } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) {\n            $prefix = substr($prefix, 0, -1);\n        }\n\n        $this->line .= $prefix;\n\n        if ($hasChild) {\n            $this->dumpLine($cursor->depth);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut)\n    {\n        if (empty($cursor->attr['cut_hash'])) {\n            $this->dumpEllipsis($cursor, $hasChild, $cut);\n            $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : ''));\n        }\n\n        $this->endValue($cursor);\n    }\n\n    /**\n     * Dumps an ellipsis for cut children.\n     *\n     * @param bool $hasChild When the dump of the hash has child item\n     * @param int  $cut      The number of items the hash has been cut by\n     */\n    protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut)\n    {\n        if ($cut) {\n            $this->line .= ' …';\n            if (0 < $cut) {\n                $this->line .= $cut;\n            }\n            if ($hasChild) {\n                $this->dumpLine($cursor->depth + 1);\n            }\n        }\n    }\n\n    /**\n     * Dumps a key in a hash structure.\n     */\n    protected function dumpKey(Cursor $cursor)\n    {\n        if (null !== $key = $cursor->hashKey) {\n            if ($cursor->hashKeyIsBinary) {\n                $key = $this->utf8Encode($key);\n            }\n            $attr = ['binary' => $cursor->hashKeyIsBinary];\n            $bin = $cursor->hashKeyIsBinary ? 'b' : '';\n            $style = 'key';\n            switch ($cursor->hashType) {\n                default:\n                case Cursor::HASH_INDEXED:\n                    if (self::DUMP_LIGHT_ARRAY & $this->flags) {\n                        break;\n                    }\n                    $style = 'index';\n                    // no break\n                case Cursor::HASH_ASSOC:\n                    if (\\is_int($key)) {\n                        $this->line .= $this->style($style, $key).' => ';\n                    } else {\n                        $this->line .= $bin.'\"'.$this->style($style, $key).'\" => ';\n                    }\n                    break;\n\n                case Cursor::HASH_RESOURCE:\n                    $key = \"\\0~\\0\".$key;\n                    // no break\n                case Cursor::HASH_OBJECT:\n                    if (!isset($key[0]) || \"\\0\" !== $key[0]) {\n                        $this->line .= '+'.$bin.$this->style('public', $key).': ';\n                    } elseif (0 < strpos($key, \"\\0\", 1)) {\n                        $key = explode(\"\\0\", substr($key, 1), 2);\n\n                        switch ($key[0][0]) {\n                            case '+': // User inserted keys\n                                $attr['dynamic'] = true;\n                                $this->line .= '+'.$bin.'\"'.$this->style('public', $key[1], $attr).'\": ';\n                                break 2;\n                            case '~':\n                                $style = 'meta';\n                                if (isset($key[0][1])) {\n                                    parse_str(substr($key[0], 1), $attr);\n                                    $attr += ['binary' => $cursor->hashKeyIsBinary];\n                                }\n                                break;\n                            case '*':\n                                $style = 'protected';\n                                $bin = '#'.$bin;\n                                break;\n                            default:\n                                $attr['class'] = $key[0];\n                                $style = 'private';\n                                $bin = '-'.$bin;\n                                break;\n                        }\n\n                        if (isset($attr['collapse'])) {\n                            if ($attr['collapse']) {\n                                $this->collapseNextHash = true;\n                            } else {\n                                $this->expandNextHash = true;\n                            }\n                        }\n\n                        $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': ');\n                    } else {\n                        // This case should not happen\n                        $this->line .= '-'.$bin.'\"'.$this->style('private', $key, ['class' => '']).'\": ';\n                    }\n                    break;\n            }\n\n            if ($cursor->hardRefTo) {\n                $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' ';\n            }\n        }\n    }\n\n    /**\n     * Decorates a value with some style.\n     *\n     * @param string $style The type of style being applied\n     * @param string $value The value being styled\n     * @param array  $attr  Optional context information\n     *\n     * @return string\n     */\n    protected function style(string $style, string $value, array $attr = [])\n    {\n        if (null === $this->colors) {\n            $this->colors = $this->supportsColors();\n        }\n\n        if (null === $this->handlesHrefGracefully) {\n            $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')\n                && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);\n        }\n\n        if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {\n            $prefix = substr($value, 0, -$attr['ellipsis']);\n            if ('cli' === \\PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\\\' === \\DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) {\n                $prefix = '.'.substr($prefix, \\strlen($_SERVER[$pwd]));\n            }\n            if (!empty($attr['ellipsis-tail'])) {\n                $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']);\n                $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']);\n            } else {\n                $value = substr($value, -$attr['ellipsis']);\n            }\n\n            $value = $this->style('default', $prefix).$this->style($style, $value);\n\n            goto href;\n        }\n\n        $map = static::$controlCharsMap;\n        $startCchr = $this->colors ? \"\\033[m\\033[{$this->styles['default']}m\" : '';\n        $endCchr = $this->colors ? \"\\033[m\\033[{$this->styles[$style]}m\" : '';\n        $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) {\n            $s = $startCchr;\n            $c = $c[$i = 0];\n            do {\n                $s .= $map[$c[$i]] ?? sprintf('\\x%02X', \\ord($c[$i]));\n            } while (isset($c[++$i]));\n\n            return $s.$endCchr;\n        }, $value, -1, $cchrCount);\n\n        if ($this->colors) {\n            if ($cchrCount && \"\\033\" === $value[0]) {\n                $value = substr($value, \\strlen($startCchr));\n            } else {\n                $value = \"\\033[{$this->styles[$style]}m\".$value;\n            }\n            if ($cchrCount && str_ends_with($value, $endCchr)) {\n                $value = substr($value, 0, -\\strlen($endCchr));\n            } else {\n                $value .= \"\\033[{$this->styles['default']}m\";\n            }\n        }\n\n        href:\n        if ($this->colors && $this->handlesHrefGracefully) {\n            if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {\n                if ('note' === $style) {\n                    $value .= \"\\033]8;;{$href}\\033\\\\^\\033]8;;\\033\\\\\";\n                } else {\n                    $attr['href'] = $href;\n                }\n            }\n            if (isset($attr['href'])) {\n                $value = \"\\033]8;;{$attr['href']}\\033\\\\{$value}\\033]8;;\\033\\\\\";\n            }\n        } elseif ($attr['if_links'] ?? false) {\n            return '';\n        }\n\n        return $value;\n    }\n\n    /**\n     * @return bool\n     */\n    protected function supportsColors()\n    {\n        if ($this->outputStream !== static::$defaultOutput) {\n            return $this->hasColorSupport($this->outputStream);\n        }\n        if (null !== static::$defaultColors) {\n            return static::$defaultColors;\n        }\n        if (isset($_SERVER['argv'][1])) {\n            $colors = $_SERVER['argv'];\n            $i = \\count($colors);\n            while (--$i > 0) {\n                if (isset($colors[$i][5])) {\n                    switch ($colors[$i]) {\n                        case '--ansi':\n                        case '--color':\n                        case '--color=yes':\n                        case '--color=force':\n                        case '--color=always':\n                        case '--colors=always':\n                            return static::$defaultColors = true;\n\n                        case '--no-ansi':\n                        case '--color=no':\n                        case '--color=none':\n                        case '--color=never':\n                        case '--colors=never':\n                            return static::$defaultColors = false;\n                    }\n                }\n            }\n        }\n\n        $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null];\n        $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream;\n\n        return static::$defaultColors = $this->hasColorSupport($h);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function dumpLine(int $depth, bool $endOfValue = false)\n    {\n        if ($this->colors) {\n            $this->line = sprintf(\"\\033[%sm%s\\033[m\", $this->styles['default'], $this->line);\n        }\n        parent::dumpLine($depth);\n    }\n\n    protected function endValue(Cursor $cursor)\n    {\n        if (-1 === $cursor->hashType) {\n            return;\n        }\n\n        if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {\n            if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {\n                $this->line .= ',';\n            } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) {\n                $this->line .= ',';\n            }\n        }\n\n        $this->dumpLine($cursor->depth, true);\n    }\n\n    /**\n     * Returns true if the stream supports colorization.\n     *\n     * Reference: Composer\\XdebugHandler\\Process::supportsColor\n     * https://github.com/composer/xdebug-handler\n     *\n     * @param mixed $stream A CLI output stream\n     */\n    private function hasColorSupport($stream): bool\n    {\n        if (!\\is_resource($stream) || 'stream' !== get_resource_type($stream)) {\n            return false;\n        }\n\n        // Follow https://no-color.org/\n        if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) {\n            return false;\n        }\n\n        if ('Hyper' === getenv('TERM_PROGRAM')) {\n            return true;\n        }\n\n        if (\\DIRECTORY_SEPARATOR === '\\\\') {\n            return (\\function_exists('sapi_windows_vt100_support')\n                && @sapi_windows_vt100_support($stream))\n                || false !== getenv('ANSICON')\n                || 'ON' === getenv('ConEmuANSI')\n                || 'xterm' === getenv('TERM');\n        }\n\n        return stream_isatty($stream);\n    }\n\n    /**\n     * Returns true if the Windows terminal supports true color.\n     *\n     * Note that this does not check an output stream, but relies on environment\n     * variables from known implementations, or a PHP and Windows version that\n     * supports true color.\n     */\n    private function isWindowsTrueColor(): bool\n    {\n        $result = 183 <= getenv('ANSICON_VER')\n            || 'ON' === getenv('ConEmuANSI')\n            || 'xterm' === getenv('TERM')\n            || 'Hyper' === getenv('TERM_PROGRAM');\n\n        if (!$result) {\n            $version = sprintf(\n                '%s.%s.%s',\n                PHP_WINDOWS_VERSION_MAJOR,\n                PHP_WINDOWS_VERSION_MINOR,\n                PHP_WINDOWS_VERSION_BUILD\n            );\n            $result = $version >= '10.0.15063';\n        }\n\n        return $result;\n    }\n\n    private function getSourceLink(string $file, int $line)\n    {\n        if ($fmt = $this->displayOptions['fileLinkFormat']) {\n            return \\is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\n/**\n * Tries to provide context on CLI.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nfinal class CliContextProvider implements ContextProviderInterface\n{\n    public function getContext(): ?array\n    {\n        if ('cli' !== \\PHP_SAPI) {\n            return null;\n        }\n\n        return [\n            'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []),\n            'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']),\n        ];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\n/**\n * Interface to provide contextual data about dump data clones sent to a server.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\ninterface ContextProviderInterface\n{\n    public function getContext(): ?array;\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\n\n/**\n * Tries to provide context from a request.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nfinal class RequestContextProvider implements ContextProviderInterface\n{\n    private $requestStack;\n    private $cloner;\n\n    public function __construct(RequestStack $requestStack)\n    {\n        $this->requestStack = $requestStack;\n        $this->cloner = new VarCloner();\n        $this->cloner->setMaxItems(0);\n        $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);\n    }\n\n    public function getContext(): ?array\n    {\n        if (null === $request = $this->requestStack->getCurrentRequest()) {\n            return null;\n        }\n\n        $controller = $request->attributes->get('_controller');\n\n        return [\n            'uri' => $request->getUri(),\n            'method' => $request->getMethod(),\n            'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller,\n            'identifier' => spl_object_hash($request),\n        ];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper\\ContextProvider;\n\nuse Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\VarDumper;\nuse Twig\\Template;\n\n/**\n * Tries to provide context from sources (class name, file, line, code excerpt, ...).\n *\n * @author Nicolas Grekas <p@tchwork.com>\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nfinal class SourceContextProvider implements ContextProviderInterface\n{\n    private $limit;\n    private $charset;\n    private $projectDir;\n    private $fileLinkFormatter;\n\n    public function __construct(string $charset = null, string $projectDir = null, FileLinkFormatter $fileLinkFormatter = null, int $limit = 9)\n    {\n        $this->charset = $charset;\n        $this->projectDir = $projectDir;\n        $this->fileLinkFormatter = $fileLinkFormatter;\n        $this->limit = $limit;\n    }\n\n    public function getContext(): ?array\n    {\n        $trace = debug_backtrace(\\DEBUG_BACKTRACE_PROVIDE_OBJECT | \\DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit);\n\n        $file = $trace[1]['file'];\n        $line = $trace[1]['line'];\n        $name = false;\n        $fileExcerpt = false;\n\n        for ($i = 2; $i < $this->limit; ++$i) {\n            if (isset($trace[$i]['class'], $trace[$i]['function'])\n                && 'dump' === $trace[$i]['function']\n                && VarDumper::class === $trace[$i]['class']\n            ) {\n                $file = $trace[$i]['file'] ?? $file;\n                $line = $trace[$i]['line'] ?? $line;\n\n                while (++$i < $this->limit) {\n                    if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) {\n                        $file = $trace[$i]['file'];\n                        $line = $trace[$i]['line'];\n\n                        break;\n                    } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) {\n                        $template = $trace[$i]['object'];\n                        $name = $template->getTemplateName();\n                        $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false);\n                        $info = $template->getDebugInfo();\n                        if (isset($info[$trace[$i - 1]['line']])) {\n                            $line = $info[$trace[$i - 1]['line']];\n                            $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null;\n\n                            if ($src) {\n                                $src = explode(\"\\n\", $src);\n                                $fileExcerpt = [];\n\n                                for ($i = max($line - 3, 1), $max = min($line + 3, \\count($src)); $i <= $max; ++$i) {\n                                    $fileExcerpt[] = '<li'.($i === $line ? ' class=\"selected\"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';\n                                }\n\n                                $fileExcerpt = '<ol start=\"'.max($line - 3, 1).'\">'.implode(\"\\n\", $fileExcerpt).'</ol>';\n                            }\n                        }\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n\n        if (false === $name) {\n            $name = str_replace('\\\\', '/', $file);\n            $name = substr($name, strrpos($name, '/') + 1);\n        }\n\n        $context = ['name' => $name, 'file' => $file, 'line' => $line];\n        $context['file_excerpt'] = $fileExcerpt;\n\n        if (null !== $this->projectDir) {\n            $context['project_dir'] = $this->projectDir;\n            if (str_starts_with($file, $this->projectDir)) {\n                $context['file_relative'] = ltrim(substr($file, \\strlen($this->projectDir)), \\DIRECTORY_SEPARATOR);\n            }\n        }\n\n        if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) {\n            $context['file_link'] = $fileLink;\n        }\n\n        return $context;\n    }\n\n    private function htmlEncode(string $s): string\n    {\n        $html = '';\n\n        $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset);\n        $dumper->setDumpHeader('');\n        $dumper->setDumpBoundaries('', '');\n\n        $cloner = new VarCloner();\n        $dumper->dump($cloner->cloneVar($s));\n\n        return substr(strip_tags($html), 1, -1);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\n\n/**\n * @author Kévin Thérage <therage.kevin@gmail.com>\n */\nclass ContextualizedDumper implements DataDumperInterface\n{\n    private $wrappedDumper;\n    private $contextProviders;\n\n    /**\n     * @param ContextProviderInterface[] $contextProviders\n     */\n    public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders)\n    {\n        $this->wrappedDumper = $wrappedDumper;\n        $this->contextProviders = $contextProviders;\n    }\n\n    public function dump(Data $data)\n    {\n        $context = [];\n        foreach ($this->contextProviders as $contextProvider) {\n            $context[\\get_class($contextProvider)] = $contextProvider->getContext();\n        }\n\n        $this->wrappedDumper->dump($data->withContext($context));\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/DataDumperInterface.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\n\n/**\n * DataDumperInterface for dumping Data objects.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\ninterface DataDumperInterface\n{\n    public function dump(Data $data);\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/HtmlDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Cursor;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\n\n/**\n * HtmlDumper dumps variables as HTML.\n *\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass HtmlDumper extends CliDumper\n{\n    public static $defaultOutput = 'php://output';\n\n    protected static $themes = [\n        'dark' => [\n            'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',\n            'num' => 'font-weight:bold; color:#1299DA',\n            'const' => 'font-weight:bold',\n            'str' => 'font-weight:bold; color:#56DB3A',\n            'note' => 'color:#1299DA',\n            'ref' => 'color:#A0A0A0',\n            'public' => 'color:#FFFFFF',\n            'protected' => 'color:#FFFFFF',\n            'private' => 'color:#FFFFFF',\n            'meta' => 'color:#B729D9',\n            'key' => 'color:#56DB3A',\n            'index' => 'color:#1299DA',\n            'ellipsis' => 'color:#FF8400',\n            'ns' => 'user-select:none;',\n        ],\n        'light' => [\n            'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',\n            'num' => 'font-weight:bold; color:#1299DA',\n            'const' => 'font-weight:bold',\n            'str' => 'font-weight:bold; color:#629755;',\n            'note' => 'color:#6897BB',\n            'ref' => 'color:#6E6E6E',\n            'public' => 'color:#262626',\n            'protected' => 'color:#262626',\n            'private' => 'color:#262626',\n            'meta' => 'color:#B729D9',\n            'key' => 'color:#789339',\n            'index' => 'color:#1299DA',\n            'ellipsis' => 'color:#CC7832',\n            'ns' => 'user-select:none;',\n        ],\n    ];\n\n    protected $dumpHeader;\n    protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad=\"%s\">';\n    protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>';\n    protected $dumpId = 'sf-dump';\n    protected $colors = true;\n    protected $headerIsDumped = false;\n    protected $lastDepth = -1;\n    protected $styles;\n\n    private $displayOptions = [\n        'maxDepth' => 1,\n        'maxStringLength' => 160,\n        'fileLinkFormat' => null,\n    ];\n    private $extraDisplayOptions = [];\n\n    /**\n     * {@inheritdoc}\n     */\n    public function __construct($output = null, string $charset = null, int $flags = 0)\n    {\n        AbstractDumper::__construct($output, $charset, $flags);\n        $this->dumpId = 'sf-dump-'.mt_rand();\n        $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');\n        $this->styles = static::$themes['dark'] ?? self::$themes['dark'];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setStyles(array $styles)\n    {\n        $this->headerIsDumped = false;\n        $this->styles = $styles + $this->styles;\n    }\n\n    public function setTheme(string $themeName)\n    {\n        if (!isset(static::$themes[$themeName])) {\n            throw new \\InvalidArgumentException(sprintf('Theme \"%s\" does not exist in class \"%s\".', $themeName, static::class));\n        }\n\n        $this->setStyles(static::$themes[$themeName]);\n    }\n\n    /**\n     * Configures display options.\n     *\n     * @param array $displayOptions A map of display options to customize the behavior\n     */\n    public function setDisplayOptions(array $displayOptions)\n    {\n        $this->headerIsDumped = false;\n        $this->displayOptions = $displayOptions + $this->displayOptions;\n    }\n\n    /**\n     * Sets an HTML header that will be dumped once in the output stream.\n     */\n    public function setDumpHeader(?string $header)\n    {\n        $this->dumpHeader = $header;\n    }\n\n    /**\n     * Sets an HTML prefix and suffix that will encapse every single dump.\n     */\n    public function setDumpBoundaries(string $prefix, string $suffix)\n    {\n        $this->dumpPrefix = $prefix;\n        $this->dumpSuffix = $suffix;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function dump(Data $data, $output = null, array $extraDisplayOptions = [])\n    {\n        $this->extraDisplayOptions = $extraDisplayOptions;\n        $result = parent::dump($data, $output);\n        $this->dumpId = 'sf-dump-'.mt_rand();\n\n        return $result;\n    }\n\n    /**\n     * Dumps the HTML header.\n     */\n    protected function getDumpHeader()\n    {\n        $this->headerIsDumped = $this->outputStream ?? $this->lineDumper;\n\n        if (null !== $this->dumpHeader) {\n            return $this->dumpHeader;\n        }\n\n        $line = str_replace('{$options}', json_encode($this->displayOptions, \\JSON_FORCE_OBJECT), <<<'EOHTML'\n<script>\nSfdump = window.Sfdump || (function (doc) {\n\nvar refStyle = doc.createElement('style'),\n    rxEsc = /([.*+?^${}()|\\[\\]\\/\\\\])/g,\n    idRx = /\\bsf-dump-\\d+-ref[012]\\w+\\b/,\n    keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl',\n    addEventListener = function (e, n, cb) {\n        e.addEventListener(n, cb, false);\n    };\n\nrefStyle.innerHTML = 'pre.sf-dump .sf-dump-compact, .sf-dump-str-collapse .sf-dump-str-collapse, .sf-dump-str-expand .sf-dump-str-expand { display: none; }';\n(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle);\nrefStyle = doc.createElement('style');\n(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle);\n\nif (!doc.addEventListener) {\n    addEventListener = function (element, eventName, callback) {\n        element.attachEvent('on' + eventName, function (e) {\n            e.preventDefault = function () {e.returnValue = false;};\n            e.target = e.srcElement;\n            callback(e);\n        });\n    };\n}\n\nfunction toggle(a, recursive) {\n    var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass;\n\n    if (/\\bsf-dump-compact\\b/.test(oldClass)) {\n        arrow = '▼';\n        newClass = 'sf-dump-expanded';\n    } else if (/\\bsf-dump-expanded\\b/.test(oldClass)) {\n        arrow = '▶';\n        newClass = 'sf-dump-compact';\n    } else {\n        return false;\n    }\n\n    if (doc.createEvent && s.dispatchEvent) {\n        var event = doc.createEvent('Event');\n        event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false);\n\n        s.dispatchEvent(event);\n    }\n\n    a.lastChild.innerHTML = arrow;\n    s.className = s.className.replace(/\\bsf-dump-(compact|expanded)\\b/, newClass);\n\n    if (recursive) {\n        try {\n            a = s.querySelectorAll('.'+oldClass);\n            for (s = 0; s < a.length; ++s) {\n                if (-1 == a[s].className.indexOf(newClass)) {\n                    a[s].className = newClass;\n                    a[s].previousSibling.lastChild.innerHTML = arrow;\n                }\n            }\n        } catch (e) {\n        }\n    }\n\n    return true;\n};\n\nfunction collapse(a, recursive) {\n    var s = a.nextSibling || {}, oldClass = s.className;\n\n    if (/\\bsf-dump-expanded\\b/.test(oldClass)) {\n        toggle(a, recursive);\n\n        return true;\n    }\n\n    return false;\n};\n\nfunction expand(a, recursive) {\n    var s = a.nextSibling || {}, oldClass = s.className;\n\n    if (/\\bsf-dump-compact\\b/.test(oldClass)) {\n        toggle(a, recursive);\n\n        return true;\n    }\n\n    return false;\n};\n\nfunction collapseAll(root) {\n    var a = root.querySelector('a.sf-dump-toggle');\n    if (a) {\n        collapse(a, true);\n        expand(a);\n\n        return true;\n    }\n\n    return false;\n}\n\nfunction reveal(node) {\n    var previous, parents = [];\n\n    while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) {\n        parents.push(previous);\n    }\n\n    if (0 !== parents.length) {\n        parents.forEach(function (parent) {\n            expand(parent);\n        });\n\n        return true;\n    }\n\n    return false;\n}\n\nfunction highlight(root, activeNode, nodes) {\n    resetHighlightedNodes(root);\n\n    Array.from(nodes||[]).forEach(function (node) {\n        if (!/\\bsf-dump-highlight\\b/.test(node.className)) {\n            node.className = node.className + ' sf-dump-highlight';\n        }\n    });\n\n    if (!/\\bsf-dump-highlight-active\\b/.test(activeNode.className)) {\n        activeNode.className = activeNode.className + ' sf-dump-highlight-active';\n    }\n}\n\nfunction resetHighlightedNodes(root) {\n    Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) {\n        strNode.className = strNode.className.replace(/\\bsf-dump-highlight\\b/, '');\n        strNode.className = strNode.className.replace(/\\bsf-dump-highlight-active\\b/, '');\n    });\n}\n\nreturn function (root, x) {\n    root = doc.getElementById(root);\n\n    var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || '  ').replace(rxEsc, '\\\\$1')+')+', 'm'),\n        options = {$options},\n        elt = root.getElementsByTagName('A'),\n        len = elt.length,\n        i = 0, s, h,\n        t = [];\n\n    while (i < len) t.push(elt[i++]);\n\n    for (i in x) {\n        options[i] = x[i];\n    }\n\n    function a(e, f) {\n        addEventListener(root, e, function (e, n) {\n            if ('A' == e.target.tagName) {\n                f(e.target, e);\n            } else if ('A' == e.target.parentNode.tagName) {\n                f(e.target.parentNode, e);\n            } else {\n                n = /\\bsf-dump-ellipsis\\b/.test(e.target.className) ? e.target.parentNode : e.target;\n\n                if ((n = n.nextElementSibling) && 'A' == n.tagName) {\n                    if (!/\\bsf-dump-toggle\\b/.test(n.className)) {\n                        n = n.nextElementSibling || n;\n                    }\n\n                    f(n, e, true);\n                }\n            }\n        });\n    };\n    function isCtrlKey(e) {\n        return e.ctrlKey || e.metaKey;\n    }\n    function xpathString(str) {\n        var parts = str.match(/[^'\"]+|['\"]/g).map(function (part) {\n            if (\"'\" == part)  {\n                return '\"\\'\"';\n            }\n            if ('\"' == part) {\n                return \"'\\\"'\";\n            }\n\n            return \"'\" + part + \"'\";\n        });\n\n        return \"concat(\" + parts.join(\",\") + \", '')\";\n    }\n    function xpathHasClass(className) {\n        return \"contains(concat(' ', normalize-space(@class), ' '), ' \" + className +\" ')\";\n    }\n    addEventListener(root, 'mouseover', function (e) {\n        if ('' != refStyle.innerHTML) {\n            refStyle.innerHTML = '';\n        }\n    });\n    a('mouseover', function (a, e, c) {\n        if (c) {\n            e.target.style.cursor = \"pointer\";\n        } else if (a = idRx.exec(a.className)) {\n            try {\n                refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}';\n            } catch (e) {\n            }\n        }\n    });\n    a('click', function (a, e, c) {\n        if (/\\bsf-dump-toggle\\b/.test(a.className)) {\n            e.preventDefault();\n            if (!toggle(a, isCtrlKey(e))) {\n                var r = doc.getElementById(a.getAttribute('href').substr(1)),\n                    s = r.previousSibling,\n                    f = r.parentNode,\n                    t = a.parentNode;\n                t.replaceChild(r, a);\n                f.replaceChild(a, s);\n                t.insertBefore(s, r);\n                f = f.firstChild.nodeValue.match(indentRx);\n                t = t.firstChild.nodeValue.match(indentRx);\n                if (f && t && f[0] !== t[0]) {\n                    r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\\\$1'), 'mg'), t[0]);\n                }\n                if (/\\bsf-dump-compact\\b/.test(r.className)) {\n                    toggle(s, isCtrlKey(e));\n                }\n            }\n\n            if (c) {\n            } else if (doc.getSelection) {\n                try {\n                    doc.getSelection().removeAllRanges();\n                } catch (e) {\n                    doc.getSelection().empty();\n                }\n            } else {\n                doc.selection.empty();\n            }\n        } else if (/\\bsf-dump-str-toggle\\b/.test(a.className)) {\n            e.preventDefault();\n            e = a.parentNode.parentNode;\n            e.className = e.className.replace(/\\bsf-dump-str-(expand|collapse)\\b/, a.parentNode.className);\n        }\n    });\n\n    elt = root.getElementsByTagName('SAMP');\n    len = elt.length;\n    i = 0;\n\n    while (i < len) t.push(elt[i++]);\n    len = t.length;\n\n    for (i = 0; i < len; ++i) {\n        elt = t[i];\n        if ('SAMP' == elt.tagName) {\n            a = elt.previousSibling || {};\n            if ('A' != a.tagName) {\n                a = doc.createElement('A');\n                a.className = 'sf-dump-ref';\n                elt.parentNode.insertBefore(a, elt);\n            } else {\n                a.innerHTML += ' ';\n            }\n            a.title = (a.title ? a.title+'\\n[' : '[')+keyHint+'+click] Expand all children';\n            a.innerHTML += elt.className == 'sf-dump-compact' ? '<span>▶</span>' : '<span>▼</span>';\n            a.className += ' sf-dump-toggle';\n\n            x = 1;\n            if ('sf-dump' != elt.parentNode.className) {\n                x += elt.parentNode.getAttribute('data-depth')/1;\n            }\n        } else if (/\\bsf-dump-ref\\b/.test(elt.className) && (a = elt.getAttribute('href'))) {\n            a = a.substr(1);\n            elt.className += ' '+a;\n\n            if (/[\\[{]$/.test(elt.previousSibling.nodeValue)) {\n                a = a != elt.nextSibling.id && doc.getElementById(a);\n                try {\n                    s = a.nextSibling;\n                    elt.appendChild(a);\n                    s.parentNode.insertBefore(a, s);\n                    if (/^[@#]/.test(elt.innerHTML)) {\n                        elt.innerHTML += ' <span>▶</span>';\n                    } else {\n                        elt.innerHTML = '<span>▶</span>';\n                        elt.className = 'sf-dump-ref';\n                    }\n                    elt.className += ' sf-dump-toggle';\n                } catch (e) {\n                    if ('&' == elt.innerHTML.charAt(0)) {\n                        elt.innerHTML = '…';\n                        elt.className = 'sf-dump-ref';\n                    }\n                }\n            }\n        }\n    }\n\n    if (doc.evaluate && Array.from && root.children.length > 1) {\n        root.setAttribute('tabindex', 0);\n\n        SearchState = function () {\n            this.nodes = [];\n            this.idx = 0;\n        };\n        SearchState.prototype = {\n            next: function () {\n                if (this.isEmpty()) {\n                    return this.current();\n                }\n                this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0;\n\n                return this.current();\n            },\n            previous: function () {\n                if (this.isEmpty()) {\n                    return this.current();\n                }\n                this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1);\n\n                return this.current();\n            },\n            isEmpty: function () {\n                return 0 === this.count();\n            },\n            current: function () {\n                if (this.isEmpty()) {\n                    return null;\n                }\n                return this.nodes[this.idx];\n            },\n            reset: function () {\n                this.nodes = [];\n                this.idx = 0;\n            },\n            count: function () {\n                return this.nodes.length;\n            },\n        };\n\n        function showCurrent(state)\n        {\n            var currentNode = state.current(), currentRect, searchRect;\n            if (currentNode) {\n                reveal(currentNode);\n                highlight(root, currentNode, state.nodes);\n                if ('scrollIntoView' in currentNode) {\n                    currentNode.scrollIntoView(true);\n                    currentRect = currentNode.getBoundingClientRect();\n                    searchRect = search.getBoundingClientRect();\n                    if (currentRect.top < (searchRect.top + searchRect.height)) {\n                        window.scrollBy(0, -(searchRect.top + searchRect.height + 5));\n                    }\n                }\n            }\n            counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count();\n        }\n\n        var search = doc.createElement('div');\n        search.className = 'sf-dump-search-wrapper sf-dump-search-hidden';\n        search.innerHTML = '\n            <input type=\"text\" class=\"sf-dump-search-input\">\n            <span class=\"sf-dump-search-count\">0 of 0<\\/span>\n            <button type=\"button\" class=\"sf-dump-search-input-previous\" tabindex=\"-1\">\n                <svg viewBox=\"0 0 1792 1792\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z\"\\/><\\/svg>\n            <\\/button>\n            <button type=\"button\" class=\"sf-dump-search-input-next\" tabindex=\"-1\">\n                <svg viewBox=\"0 0 1792 1792\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z\"\\/><\\/svg>\n            <\\/button>\n        ';\n        root.insertBefore(search, root.firstChild);\n\n        var state = new SearchState();\n        var searchInput = search.querySelector('.sf-dump-search-input');\n        var counter = search.querySelector('.sf-dump-search-count');\n        var searchInputTimer = 0;\n        var previousSearchQuery = '';\n\n        addEventListener(searchInput, 'keyup', function (e) {\n            var searchQuery = e.target.value;\n            /* Don't perform anything if the pressed key didn't change the query */\n            if (searchQuery === previousSearchQuery) {\n                return;\n            }\n            previousSearchQuery = searchQuery;\n            clearTimeout(searchInputTimer);\n            searchInputTimer = setTimeout(function () {\n                state.reset();\n                collapseAll(root);\n                resetHighlightedNodes(root);\n                if ('' === searchQuery) {\n                    counter.textContent = '0 of 0';\n\n                    return;\n                }\n\n                var classMatches = [\n                    \"sf-dump-str\",\n                    \"sf-dump-key\",\n                    \"sf-dump-public\",\n                    \"sf-dump-protected\",\n                    \"sf-dump-private\",\n                ].map(xpathHasClass).join(' or ');\n\n                var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);\n\n                while (node = xpathResult.iterateNext()) state.nodes.push(node);\n\n                showCurrent(state);\n            }, 400);\n        });\n\n        Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) {\n            addEventListener(btn, 'click', function (e) {\n                e.preventDefault();\n                -1 !== e.target.className.indexOf('next') ? state.next() : state.previous();\n                searchInput.focus();\n                collapseAll(root);\n                showCurrent(state);\n            })\n        });\n\n        addEventListener(root, 'keydown', function (e) {\n            var isSearchActive = !/\\bsf-dump-search-hidden\\b/.test(search.className);\n            if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) {\n                /* F3 or CMD/CTRL + F */\n                if (70 === e.keyCode && document.activeElement === searchInput) {\n                   /*\n                    * If CMD/CTRL + F is hit while having focus on search input,\n                    * the user probably meant to trigger browser search instead.\n                    * Let the browser execute its behavior:\n                    */\n                    return;\n                }\n\n                e.preventDefault();\n                search.className = search.className.replace(/\\bsf-dump-search-hidden\\b/, '');\n                searchInput.focus();\n            } else if (isSearchActive) {\n                if (27 === e.keyCode) {\n                    /* ESC key */\n                    search.className += ' sf-dump-search-hidden';\n                    e.preventDefault();\n                    resetHighlightedNodes(root);\n                    searchInput.value = '';\n                } else if (\n                    (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */\n                    || 13 === e.keyCode /* Enter */\n                    || 114 === e.keyCode /* F3 */\n                ) {\n                    e.preventDefault();\n                    e.shiftKey ? state.previous() : state.next();\n                    collapseAll(root);\n                    showCurrent(state);\n                }\n            }\n        });\n    }\n\n    if (0 >= options.maxStringLength) {\n        return;\n    }\n    try {\n        elt = root.querySelectorAll('.sf-dump-str');\n        len = elt.length;\n        i = 0;\n        t = [];\n\n        while (i < len) t.push(elt[i++]);\n        len = t.length;\n\n        for (i = 0; i < len; ++i) {\n            elt = t[i];\n            s = elt.innerText || elt.textContent;\n            x = s.length - options.maxStringLength;\n            if (0 < x) {\n                h = elt.innerHTML;\n                elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);\n                elt.className += ' sf-dump-str-collapse';\n                elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class=\"sf-dump-ref sf-dump-str-toggle\" title=\"Collapse\"> ◀</a></span>'+\n                    '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class=\"sf-dump-ref sf-dump-str-toggle\" title=\"'+x+' remaining characters\"> ▶</a></span>';\n            }\n        }\n    } catch (e) {\n    }\n};\n\n})(document);\n</script><style>\npre.sf-dump {\n    display: block;\n    white-space: pre;\n    padding: 5px;\n    overflow: initial !important;\n}\npre.sf-dump:after {\n   content: \"\";\n   visibility: hidden;\n   display: block;\n   height: 0;\n   clear: both;\n}\npre.sf-dump span {\n    display: inline;\n}\npre.sf-dump a {\n    text-decoration: none;\n    cursor: pointer;\n    border: 0;\n    outline: none;\n    color: inherit;\n}\npre.sf-dump img {\n    max-width: 50em;\n    max-height: 50em;\n    margin: .5em 0 0 0;\n    padding: 0;\n    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3;\n}\npre.sf-dump .sf-dump-ellipsis {\n    display: inline-block;\n    overflow: visible;\n    text-overflow: ellipsis;\n    max-width: 5em;\n    white-space: nowrap;\n    overflow: hidden;\n    vertical-align: top;\n}\npre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis {\n    max-width: none;\n}\npre.sf-dump code {\n    display:inline;\n    padding:0;\n    background:none;\n}\n.sf-dump-public.sf-dump-highlight,\n.sf-dump-protected.sf-dump-highlight,\n.sf-dump-private.sf-dump-highlight,\n.sf-dump-str.sf-dump-highlight,\n.sf-dump-key.sf-dump-highlight {\n    background: rgba(111, 172, 204, 0.3);\n    border: 1px solid #7DA0B1;\n    border-radius: 3px;\n}\n.sf-dump-public.sf-dump-highlight-active,\n.sf-dump-protected.sf-dump-highlight-active,\n.sf-dump-private.sf-dump-highlight-active,\n.sf-dump-str.sf-dump-highlight-active,\n.sf-dump-key.sf-dump-highlight-active {\n    background: rgba(253, 175, 0, 0.4);\n    border: 1px solid #ffa500;\n    border-radius: 3px;\n}\npre.sf-dump .sf-dump-search-hidden {\n    display: none !important;\n}\npre.sf-dump .sf-dump-search-wrapper {\n    font-size: 0;\n    white-space: nowrap;\n    margin-bottom: 5px;\n    display: flex;\n    position: -webkit-sticky;\n    position: sticky;\n    top: 5px;\n}\npre.sf-dump .sf-dump-search-wrapper > * {\n    vertical-align: top;\n    box-sizing: border-box;\n    height: 21px;\n    font-weight: normal;\n    border-radius: 0;\n    background: #FFF;\n    color: #757575;\n    border: 1px solid #BBB;\n}\npre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {\n    padding: 3px;\n    height: 21px;\n    font-size: 12px;\n    border-right: none;\n    border-top-left-radius: 3px;\n    border-bottom-left-radius: 3px;\n    color: #000;\n    min-width: 15px;\n    width: 100%;\n}\npre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next,\npre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous {\n    background: #F2F2F2;\n    outline: none;\n    border-left: none;\n    font-size: 0;\n    line-height: 0;\n}\npre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next {\n    border-top-right-radius: 3px;\n    border-bottom-right-radius: 3px;\n}\npre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,\npre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {\n    pointer-events: none;\n    width: 12px;\n    height: 12px;\n}\npre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count {\n    display: inline-block;\n    padding: 0 5px;\n    margin: 0;\n    border-left: none;\n    line-height: 21px;\n    font-size: 12px;\n}\nEOHTML\n        );\n\n        foreach ($this->styles as $class => $style) {\n            $line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}';\n        }\n        $line .= 'pre.sf-dump .sf-dump-ellipsis-note{'.$this->styles['note'].'}';\n\n        return $this->dumpHeader = preg_replace('/\\s+/', ' ', $line).'</style>'.$this->dumpHeader;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)\n    {\n        if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) {\n            $this->dumpKey($cursor);\n            $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []);\n            $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' <samp class=sf-dump-compact>' : ' <samp class=sf-dump-expanded>';\n            $this->endValue($cursor);\n            $this->line .= $this->indentPad;\n            $this->line .= sprintf('<img src=\"data:%s;base64,%s\" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data']));\n            $this->endValue($cursor);\n        } else {\n            parent::dumpString($cursor, $str, $bin, $cut);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild)\n    {\n        if (Cursor::HASH_OBJECT === $type) {\n            $cursor->attr['depth'] = $cursor->depth;\n        }\n        parent::enterHash($cursor, $type, $class, false);\n\n        if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) {\n            $cursor->skipChildren = false;\n            $eol = ' class=sf-dump-compact>';\n        } else {\n            $this->expandNextHash = false;\n            $eol = ' class=sf-dump-expanded>';\n        }\n\n        if ($hasChild) {\n            $this->line .= '<samp data-depth='.($cursor->depth + 1);\n            if ($cursor->refIndex) {\n                $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2;\n                $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex;\n\n                $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r);\n            }\n            $this->line .= $eol;\n            $this->dumpLine($cursor->depth);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut)\n    {\n        $this->dumpEllipsis($cursor, $hasChild, $cut);\n        if ($hasChild) {\n            $this->line .= '</samp>';\n        }\n        parent::leaveHash($cursor, $type, $class, $hasChild, 0);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function style(string $style, string $value, array $attr = [])\n    {\n        if ('' === $value) {\n            return '';\n        }\n\n        $v = esc($value);\n\n        if ('ref' === $style) {\n            if (empty($attr['count'])) {\n                return sprintf('<a class=sf-dump-ref>%s</a>', $v);\n            }\n            $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1);\n\n            return sprintf('<a class=sf-dump-ref href=#%s-ref%s title=\"%d occurrences\">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);\n        }\n\n        if ('const' === $style && isset($attr['value'])) {\n            $style .= sprintf(' title=\"%s\"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));\n        } elseif ('public' === $style) {\n            $style .= sprintf(' title=\"%s\"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');\n        } elseif ('str' === $style && 1 < $attr['length']) {\n            $style .= sprintf(' title=\"%d%s characters\"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');\n        } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\\\')) {\n            $style .= ' title=\"\"';\n            $attr += [\n                'ellipsis' => \\strlen($value) - $c,\n                'ellipsis-type' => 'note',\n                'ellipsis-tail' => 1,\n            ];\n        } elseif ('protected' === $style) {\n            $style .= ' title=\"Protected property\"';\n        } elseif ('meta' === $style && isset($attr['title'])) {\n            $style .= sprintf(' title=\"%s\"', esc($this->utf8Encode($attr['title'])));\n        } elseif ('private' === $style) {\n            $style .= sprintf(' title=\"Private property defined in class:&#10;`%s`\"', esc($this->utf8Encode($attr['class'])));\n        }\n        $map = static::$controlCharsMap;\n\n        if (isset($attr['ellipsis'])) {\n            $class = 'sf-dump-ellipsis';\n            if (isset($attr['ellipsis-type'])) {\n                $class = sprintf('\"%s sf-dump-ellipsis-%s\"', $class, $attr['ellipsis-type']);\n            }\n            $label = esc(substr($value, -$attr['ellipsis']));\n            $style = str_replace(' title=\"', \" title=\\\"$v\\n\", $style);\n            $v = sprintf('<span class=%s>%s</span>', $class, substr($v, 0, -\\strlen($label)));\n\n            if (!empty($attr['ellipsis-tail'])) {\n                $tail = \\strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail'])));\n                $v .= sprintf('<span class=%s>%s</span>%s', $class, substr($label, 0, $tail), substr($label, $tail));\n            } else {\n                $v .= $label;\n            }\n        }\n\n        $v = \"<span class=sf-dump-{$style}>\".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {\n            $s = $b = '<span class=\"sf-dump-default';\n            $c = $c[$i = 0];\n            if ($ns = \"\\r\" === $c[$i] || \"\\n\" === $c[$i]) {\n                $s .= ' sf-dump-ns';\n            }\n            $s .= '\">';\n            do {\n                if ((\"\\r\" === $c[$i] || \"\\n\" === $c[$i]) !== $ns) {\n                    $s .= '</span>'.$b;\n                    if ($ns = !$ns) {\n                        $s .= ' sf-dump-ns';\n                    }\n                    $s .= '\">';\n                }\n\n                $s .= $map[$c[$i]] ?? sprintf('\\x%02X', \\ord($c[$i]));\n            } while (isset($c[++$i]));\n\n            return $s.'</span>';\n        }, $v).'</span>';\n\n        if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {\n            $attr['href'] = $href;\n        }\n        if (isset($attr['href'])) {\n            $target = isset($attr['file']) ? '' : ' target=\"_blank\"';\n            $v = sprintf('<a href=\"%s\"%s rel=\"noopener noreferrer\">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v);\n        }\n        if (isset($attr['lang'])) {\n            $v = sprintf('<code class=\"%s\">%s</code>', esc($attr['lang']), $v);\n        }\n\n        return $v;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function dumpLine(int $depth, bool $endOfValue = false)\n    {\n        if (-1 === $this->lastDepth) {\n            $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;\n        }\n        if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) {\n            $this->line = $this->getDumpHeader().$this->line;\n        }\n\n        if (-1 === $depth) {\n            $args = ['\"'.$this->dumpId.'\"'];\n            if ($this->extraDisplayOptions) {\n                $args[] = json_encode($this->extraDisplayOptions, \\JSON_FORCE_OBJECT);\n            }\n            // Replace is for BC\n            $this->line .= sprintf(str_replace('\"%s\"', '%s', $this->dumpSuffix), implode(', ', $args));\n        }\n        $this->lastDepth = $depth;\n\n        $this->line = mb_encode_numericentity($this->line, [0x80, 0xFFFF, 0, 0xFFFF], 'UTF-8');\n\n        if (-1 === $depth) {\n            AbstractDumper::dumpLine(0);\n        }\n        AbstractDumper::dumpLine($depth);\n    }\n\n    private function getSourceLink(string $file, int $line)\n    {\n        $options = $this->extraDisplayOptions + $this->displayOptions;\n\n        if ($fmt = $options['fileLinkFormat']) {\n            return \\is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);\n        }\n\n        return false;\n    }\n}\n\nfunction esc(string $str)\n{\n    return htmlspecialchars($str, \\ENT_QUOTES, 'UTF-8');\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Dumper/ServerDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Dumper;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\nuse Symfony\\Component\\VarDumper\\Server\\Connection;\n\n/**\n * ServerDumper forwards serialized Data clones to a server.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nclass ServerDumper implements DataDumperInterface\n{\n    private $connection;\n    private $wrappedDumper;\n\n    /**\n     * @param string                     $host             The server host\n     * @param DataDumperInterface|null   $wrappedDumper    A wrapped instance used whenever we failed contacting the server\n     * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name\n     */\n    public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = [])\n    {\n        $this->connection = new Connection($host, $contextProviders);\n        $this->wrappedDumper = $wrappedDumper;\n    }\n\n    public function getContextProviders(): array\n    {\n        return $this->connection->getContextProviders();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function dump(Data $data)\n    {\n        if (!$this->connection->write($data) && $this->wrappedDumper) {\n            $this->wrappedDumper->dump($data);\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Exception/ThrowingCasterException.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Exception;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass ThrowingCasterException extends \\Exception\n{\n    /**\n     * @param \\Throwable $prev The exception thrown from the caster\n     */\n    public function __construct(\\Throwable $prev)\n    {\n        parent::__construct('Unexpected '.\\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/LICENSE",
    "content": "Copyright (c) 2014-2022 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "vendor/symfony/var-dumper/README.md",
    "content": "VarDumper Component\n===================\n\nThe VarDumper component provides mechanisms for walking through any arbitrary\nPHP variable. It provides a better `dump()` function that you can use instead\nof `var_dump()`.\n\nResources\n---------\n\n * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html)\n * [Contributing](https://symfony.com/doc/current/contributing/index.html)\n * [Report issues](https://github.com/symfony/symfony/issues) and\n   [send Pull Requests](https://github.com/symfony/symfony/pulls)\n   in the [main Symfony repository](https://github.com/symfony/symfony)\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Resources/bin/var-dump-server",
    "content": "#!/usr/bin/env php\n<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\n/**\n * Starts a dump server to collect and output dumps on a single place with multiple formats support.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\n\nuse Psr\\Log\\LoggerInterface;\nuse Symfony\\Component\\Console\\Application;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Logger\\ConsoleLogger;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\nuse Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand;\nuse Symfony\\Component\\VarDumper\\Server\\DumpServer;\n\nfunction includeIfExists(string $file): bool\n{\n    return file_exists($file) && include $file;\n}\n\nif (\n    !includeIfExists(__DIR__ . '/../../../../autoload.php') &&\n    !includeIfExists(__DIR__ . '/../../vendor/autoload.php') &&\n    !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')\n) {\n    fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL);\n    exit(1);\n}\n\nif (!class_exists(Application::class)) {\n    fwrite(STDERR, 'You need the \"symfony/console\" component in order to run the VarDumper server.'.PHP_EOL);\n    exit(1);\n}\n\n$input = new ArgvInput();\n$output = new ConsoleOutput();\n$defaultHost = '127.0.0.1:9912';\n$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true);\n$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null;\n\n$app = new Application();\n\n$app->getDefinition()->addOption(\n    new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost)\n);\n\n$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger)))\n    ->getApplication()\n    ->setDefaultCommand($command->getName(), true)\n    ->run($input, $output)\n;\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css",
    "content": "body {\n    display: flex;\n    flex-direction: column-reverse;\n    justify-content: flex-end;\n    max-width: 1140px;\n    margin: auto;\n    padding: 15px;\n    word-wrap: break-word;\n    background-color: #F9F9F9;\n    color: #222;\n    font-family: Helvetica, Arial, sans-serif;\n    font-size: 14px;\n    line-height: 1.4;\n}\np {\n    margin: 0;\n}\na {\n    color: #218BC3;\n    text-decoration: none;\n}\na:hover {\n    text-decoration: underline;\n}\n.text-small {\n    font-size: 12px !important;\n}\narticle {\n    margin: 5px;\n    margin-bottom: 10px;\n}\narticle > header > .row {\n    display: flex;\n    flex-direction: row;\n    align-items: baseline;\n    margin-bottom: 10px;\n}\narticle > header > .row > .col {\n    flex: 1;\n    display: flex;\n    align-items: baseline;\n}\narticle > header > .row > h2 {\n    font-size: 14px;\n    color: #222;\n    font-weight: normal;\n    font-family: \"Lucida Console\", monospace, sans-serif;\n    word-break: break-all;\n    margin: 20px 5px 0 0;\n    user-select: all;\n}\narticle > header > .row > h2 > code {\n    white-space: nowrap;\n    user-select: none;\n    color: #cc2255;\n    background-color: #f7f7f9;\n    border: 1px solid #e1e1e8;\n    border-radius: 3px;\n    margin-right: 5px;\n    padding: 0 3px;\n}\narticle > header > .row > time.col {\n    flex: 0;\n    text-align: right;\n    white-space: nowrap;\n    color: #999;\n    font-style: italic;\n}\narticle > header ul.tags {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n    font-size: 12px;\n}\narticle > header ul.tags > li {\n    user-select: all;\n    margin-bottom: 2px;\n}\narticle > header ul.tags > li > span.badge {\n    display: inline-block;\n    padding: .25em .4em;\n    margin-right: 5px;\n    border-radius: 4px;\n    background-color: #6c757d3b;\n    color: #524d4d;\n    font-size: 12px;\n    text-align: center;\n    font-weight: 700;\n    line-height: 1;\n    white-space: nowrap;\n    vertical-align: baseline;\n    user-select: none;\n}\narticle > section.body {\n    border: 1px solid #d8d8d8;\n    background: #FFF;\n    padding: 10px;\n    border-radius: 3px;\n}\npre.sf-dump {\n    border-radius: 3px;\n    margin-bottom: 0;\n}\n.hidden {\n    display: none !important;\n}\n.dumped-tag > .sf-dump {\n    display: inline-block;\n    margin: 0;\n    padding: 1px 5px;\n    line-height: 1.4;\n    vertical-align: top;\n    background-color: transparent;\n    user-select: auto;\n}\n.dumped-tag > pre.sf-dump,\n.dumped-tag > .sf-dump-default {\n    color: #CC7832;\n    background: none;\n}\n.dumped-tag > .sf-dump .sf-dump-str { color: #629755; }\n.dumped-tag > .sf-dump .sf-dump-private,\n.dumped-tag > .sf-dump .sf-dump-protected,\n.dumped-tag > .sf-dump .sf-dump-public { color: #262626; }\n.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; }\n.dumped-tag > .sf-dump .sf-dump-key { color: #789339; }\n.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; }\n.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; }\n.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; }\n.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; }\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Resources/functions/dump.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nuse Symfony\\Component\\VarDumper\\VarDumper;\n\nif (!function_exists('dump')) {\n    /**\n     * @author Nicolas Grekas <p@tchwork.com>\n     */\n    function dump($var, ...$moreVars)\n    {\n        VarDumper::dump($var);\n\n        foreach ($moreVars as $v) {\n            VarDumper::dump($v);\n        }\n\n        if (1 < func_num_args()) {\n            return func_get_args();\n        }\n\n        return $var;\n    }\n}\n\nif (!function_exists('dd')) {\n    /**\n     * @return never\n     */\n    function dd(...$vars)\n    {\n        if (!in_array(\\PHP_SAPI, ['cli', 'phpdbg'], true) && !headers_sent()) {\n            header('HTTP/1.1 500 Internal Server Error');\n        }\n\n        foreach ($vars as $v) {\n            VarDumper::dump($v);\n        }\n\n        exit(1);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js",
    "content": "document.addEventListener('DOMContentLoaded', function() {\n  let prev = null;\n  Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) {\n    const dedupId = article.dataset.dedupId;\n    if (dedupId === prev) {\n      article.getElementsByTagName('header')[0].classList.add('hidden');\n    }\n    prev = dedupId;\n  });\n});\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Server/Connection.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Server;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface;\n\n/**\n * Forwards serialized Data clones to a server.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n */\nclass Connection\n{\n    private $host;\n    private $contextProviders;\n\n    /**\n     * @var resource|null\n     */\n    private $socket;\n\n    /**\n     * @param string                     $host             The server host\n     * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name\n     */\n    public function __construct(string $host, array $contextProviders = [])\n    {\n        if (!str_contains($host, '://')) {\n            $host = 'tcp://'.$host;\n        }\n\n        $this->host = $host;\n        $this->contextProviders = $contextProviders;\n    }\n\n    public function getContextProviders(): array\n    {\n        return $this->contextProviders;\n    }\n\n    public function write(Data $data): bool\n    {\n        $socketIsFresh = !$this->socket;\n        if (!$this->socket = $this->socket ?: $this->createSocket()) {\n            return false;\n        }\n\n        $context = ['timestamp' => microtime(true)];\n        foreach ($this->contextProviders as $name => $provider) {\n            $context[$name] = $provider->getContext();\n        }\n        $context = array_filter($context);\n        $encodedPayload = base64_encode(serialize([$data, $context])).\"\\n\";\n\n        set_error_handler([self::class, 'nullErrorHandler']);\n        try {\n            if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {\n                return true;\n            }\n            if (!$socketIsFresh) {\n                stream_socket_shutdown($this->socket, \\STREAM_SHUT_RDWR);\n                fclose($this->socket);\n                $this->socket = $this->createSocket();\n            }\n            if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {\n                return true;\n            }\n        } finally {\n            restore_error_handler();\n        }\n\n        return false;\n    }\n\n    private static function nullErrorHandler(int $t, string $m)\n    {\n        // no-op\n    }\n\n    private function createSocket()\n    {\n        set_error_handler([self::class, 'nullErrorHandler']);\n        try {\n            return stream_socket_client($this->host, $errno, $errstr, 3, \\STREAM_CLIENT_CONNECT | \\STREAM_CLIENT_ASYNC_CONNECT);\n        } finally {\n            restore_error_handler();\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Server/DumpServer.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Server;\n\nuse Psr\\Log\\LoggerInterface;\nuse Symfony\\Component\\VarDumper\\Cloner\\Data;\nuse Symfony\\Component\\VarDumper\\Cloner\\Stub;\n\n/**\n * A server collecting Data clones sent by a ServerDumper.\n *\n * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>\n *\n * @final\n */\nclass DumpServer\n{\n    private $host;\n    private $logger;\n\n    /**\n     * @var resource|null\n     */\n    private $socket;\n\n    public function __construct(string $host, LoggerInterface $logger = null)\n    {\n        if (!str_contains($host, '://')) {\n            $host = 'tcp://'.$host;\n        }\n\n        $this->host = $host;\n        $this->logger = $logger;\n    }\n\n    public function start(): void\n    {\n        if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) {\n            throw new \\RuntimeException(sprintf('Server start failed on \"%s\": ', $this->host).$errstr.' '.$errno);\n        }\n    }\n\n    public function listen(callable $callback): void\n    {\n        if (null === $this->socket) {\n            $this->start();\n        }\n\n        foreach ($this->getMessages() as $clientId => $message) {\n            if ($this->logger) {\n                $this->logger->info('Received a payload from client {clientId}', ['clientId' => $clientId]);\n            }\n\n            $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]);\n\n            // Impossible to decode the message, give up.\n            if (false === $payload) {\n                if ($this->logger) {\n                    $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]);\n                }\n\n                continue;\n            }\n\n            if (!\\is_array($payload) || \\count($payload) < 2 || !$payload[0] instanceof Data || !\\is_array($payload[1])) {\n                if ($this->logger) {\n                    $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]);\n                }\n\n                continue;\n            }\n\n            [$data, $context] = $payload;\n\n            $callback($data, $context, $clientId);\n        }\n    }\n\n    public function getHost(): string\n    {\n        return $this->host;\n    }\n\n    private function getMessages(): iterable\n    {\n        $sockets = [(int) $this->socket => $this->socket];\n        $write = [];\n\n        while (true) {\n            $read = $sockets;\n            stream_select($read, $write, $write, null);\n\n            foreach ($read as $stream) {\n                if ($this->socket === $stream) {\n                    $stream = stream_socket_accept($this->socket);\n                    $sockets[(int) $stream] = $stream;\n                } elseif (feof($stream)) {\n                    unset($sockets[(int) $stream]);\n                    fclose($stream);\n                } else {\n                    yield (int) $stream => fgets($stream);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/Test/VarDumperTestTrait.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper\\Test;\n\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\ntrait VarDumperTestTrait\n{\n    /**\n     * @internal\n     */\n    private $varDumperConfig = [\n        'casters' => [],\n        'flags' => null,\n    ];\n\n    protected function setUpVarDumper(array $casters, int $flags = null): void\n    {\n        $this->varDumperConfig['casters'] = $casters;\n        $this->varDumperConfig['flags'] = $flags;\n    }\n\n    /**\n     * @after\n     */\n    protected function tearDownVarDumper(): void\n    {\n        $this->varDumperConfig['casters'] = [];\n        $this->varDumperConfig['flags'] = null;\n    }\n\n    public function assertDumpEquals($expected, $data, int $filter = 0, string $message = '')\n    {\n        $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);\n    }\n\n    public function assertDumpMatchesFormat($expected, $data, int $filter = 0, string $message = '')\n    {\n        $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);\n    }\n\n    protected function getDump($data, $key = null, int $filter = 0): ?string\n    {\n        if (null === $flags = $this->varDumperConfig['flags']) {\n            $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0;\n            $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0;\n            $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0;\n        }\n\n        $cloner = new VarCloner();\n        $cloner->addCasters($this->varDumperConfig['casters']);\n        $cloner->setMaxItems(-1);\n        $dumper = new CliDumper(null, null, $flags);\n        $dumper->setColors(false);\n        $data = $cloner->cloneVar($data, $filter)->withRefHandles(false);\n        if (null !== $key && null === $data = $data->seek($key)) {\n            return null;\n        }\n\n        return rtrim($dumper->dump($data, true));\n    }\n\n    private function prepareExpectation($expected, int $filter): string\n    {\n        if (!\\is_string($expected)) {\n            $expected = $this->getDump($expected, null, $filter);\n        }\n\n        return rtrim($expected);\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/VarDumper.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Symfony\\Component\\VarDumper;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter;\nuse Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster;\nuse Symfony\\Component\\VarDumper\\Cloner\\VarCloner;\nuse Symfony\\Component\\VarDumper\\Dumper\\CliDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider;\nuse Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper;\nuse Symfony\\Component\\VarDumper\\Dumper\\ServerDumper;\n\n// Load the global dump() function\nrequire_once __DIR__.'/Resources/functions/dump.php';\n\n/**\n * @author Nicolas Grekas <p@tchwork.com>\n */\nclass VarDumper\n{\n    /**\n     * @var callable|null\n     */\n    private static $handler;\n\n    public static function dump($var)\n    {\n        if (null === self::$handler) {\n            self::register();\n        }\n\n        return (self::$handler)($var);\n    }\n\n    /**\n     * @return callable|null\n     */\n    public static function setHandler(callable $callable = null)\n    {\n        $prevHandler = self::$handler;\n\n        // Prevent replacing the handler with expected format as soon as the env var was set:\n        if (isset($_SERVER['VAR_DUMPER_FORMAT'])) {\n            return $prevHandler;\n        }\n\n        self::$handler = $callable;\n\n        return $prevHandler;\n    }\n\n    private static function register(): void\n    {\n        $cloner = new VarCloner();\n        $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);\n\n        $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null;\n        switch (true) {\n            case 'html' === $format:\n                $dumper = new HtmlDumper();\n                break;\n            case 'cli' === $format:\n                $dumper = new CliDumper();\n                break;\n            case 'server' === $format:\n            case $format && 'tcp' === parse_url($format, \\PHP_URL_SCHEME):\n                $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format;\n                $dumper = \\in_array(\\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();\n                $dumper = new ServerDumper($host, $dumper, self::getDefaultContextProviders());\n                break;\n            default:\n                $dumper = \\in_array(\\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();\n        }\n\n        if (!$dumper instanceof ServerDumper) {\n            $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);\n        }\n\n        self::$handler = function ($var) use ($cloner, $dumper) {\n            $dumper->dump($cloner->cloneVar($var));\n        };\n    }\n\n    private static function getDefaultContextProviders(): array\n    {\n        $contextProviders = [];\n\n        if (!\\in_array(\\PHP_SAPI, ['cli', 'phpdbg'], true) && (class_exists(Request::class))) {\n            $requestStack = new RequestStack();\n            $requestStack->push(Request::createFromGlobals());\n            $contextProviders['request'] = new RequestContextProvider($requestStack);\n        }\n\n        $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null;\n\n        return $contextProviders + [\n            'cli' => new CliContextProvider(),\n            'source' => new SourceContextProvider(null, null, $fileLinkFormatter),\n        ];\n    }\n}\n"
  },
  {
    "path": "vendor/symfony/var-dumper/composer.json",
    "content": "{\n    \"name\": \"symfony/var-dumper\",\n    \"type\": \"library\",\n    \"description\": \"Provides mechanisms for walking through any arbitrary PHP variable\",\n    \"keywords\": [\"dump\", \"debug\"],\n    \"homepage\": \"https://symfony.com\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Nicolas Grekas\",\n            \"email\": \"p@tchwork.com\"\n        },\n        {\n            \"name\": \"Symfony Community\",\n            \"homepage\": \"https://symfony.com/contributors\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.2.5\",\n        \"symfony/polyfill-mbstring\": \"~1.0\",\n        \"symfony/polyfill-php80\": \"^1.16\"\n    },\n    \"require-dev\": {\n        \"ext-iconv\": \"*\",\n        \"symfony/console\": \"^4.4|^5.0|^6.0\",\n        \"symfony/process\": \"^4.4|^5.0|^6.0\",\n        \"symfony/uid\": \"^5.1|^6.0\",\n        \"twig/twig\": \"^2.13|^3.0.4\"\n    },\n    \"conflict\": {\n        \"phpunit/phpunit\": \"<5.4.3\",\n        \"symfony/console\": \"<4.4\"\n    },\n    \"suggest\": {\n        \"ext-iconv\": \"To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).\",\n        \"ext-intl\": \"To show region name in time zone dump\",\n        \"symfony/console\": \"To use the ServerDumpCommand and/or the bin/var-dump-server script\"\n    },\n    \"autoload\": {\n        \"files\": [ \"Resources/functions/dump.php\" ],\n        \"psr-4\": { \"Symfony\\\\Component\\\\VarDumper\\\\\": \"\" },\n        \"exclude-from-classmap\": [\n            \"/Tests/\"\n        ]\n    },\n    \"bin\": [\n        \"Resources/bin/var-dump-server\"\n    ],\n    \"minimum-stability\": \"dev\"\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/.github/workflows/run-tests.yml",
    "content": "name: Run tests\n\non: [push, pull_request]\n\njobs:\n  tests:\n    strategy:\n      matrix:\n        os: [Ubuntu, macOS]\n        php: [7.2, 7.3, 7.4, 8.0, 8.1]\n\n        include:\n          - os: Ubuntu\n            os-version: ubuntu-latest\n\n          - os: macOS\n            os-version: macos-latest\n\n    name: ${{ matrix.os }} - PHP ${{ matrix.php }}\n\n    runs-on: ${{ matrix.os-version }}\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v1\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: ${{ matrix.php }}\n          extensions: posix, dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick\n          coverage: none\n\n      - name: Install dependencies\n        run: composer update --prefer-stable --prefer-dist --no-interaction\n\n      - name: Run tests\n        run: bash upgrade.sh\n"
  },
  {
    "path": "vendor/tightenco/collect/branch-commit-push.sh",
    "content": "#!/bin/bash\n\n\nGREEN='\\033[0;32m'\nRED='\\033[0;31m'\nWHITE='\\033[0;37m'\nRESET='\\033[0m'\n\nfunction validateVersion()\n{\n    echo \"\"\n    passedVersion=$1\n    echo -e \"${WHITE}-- Validating tag '$passedVersion'...${RESET}\"\n\n    # Todo: validate the version here using a regex; if fail, just exit\n    #       ... expect 8.75.0, with no v in front of it\n\n    if [[ $passedVersion == '' ]]; then\n        echo -e \"\\n-- Invalid tag. Tags should be structured without v; e.g. 8.57.0\"\n        exit\n    fi\n\n    echo -e \"${WHITE}-- Tag valid.${RESET}\"\n    echo \"\"\n}\n\n# Exit script if any command fails (e.g. phpunit)\nset -e\n\n\n# Require confirmation it's set up corrctly\necho \necho -e \"${WHITE}-- This script is meant to be run after running upgrade.sh, BEFORE committing to Git.${RESET}\"\n\nwhile true; do\n    echo -e \"${GREEN}-- Is that the current state of your local project?${RESET}\"\n    read -p \"-- (y/n) \" yn\n    case $yn in\n        [Yy]* ) break;;\n        [Nn]* ) exit;;\n        * ) echo \"Please answer y or n.\";;\n    esac\ndone\n\n# Get the version and exit if not valid\nvalidateVersion $1\n\n# Create official v prefaced version\nversion=\"v$1\"\n\n# Run tests (and bail if they fail)\nphpunit\necho -e \"\\n${WHITE}-- Tests succeeded.${RESET}\"\n\n# Branch\necho -e \"\\n${WHITE}-- Creating a Git branch '$version-changes'...${RESET}\\n\"\ngit checkout -b $version-changes\n\n# Add and commit, with \"v8.57.0 changes\" as the commit name\ngit add -A\ngit commit -m \"$version changes\"\n\necho \necho -e \"${WHITE}-- Git committed.${RESET}\"\n\n# Push\ngit push -u origin $version-changes\n"
  },
  {
    "path": "vendor/tightenco/collect/composer.json",
    "content": "{\n    \"name\": \"tightenco/collect\",\n    \"description\": \"Collect - Illuminate Collections as a separate package.\",\n    \"keywords\": [\"laravel\", \"collection\"],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Taylor Otwell\",\n            \"email\": \"taylorotwell@gmail.com\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^7.2|^8.0\",\n        \"symfony/var-dumper\": \"^3.4 || ^4.0 || ^5.0 || ^6.0\"\n    },\n    \"require-dev\": {\n        \"mockery/mockery\": \"^1.0\",\n        \"phpunit/phpunit\": \"^8.3\",\n        \"nesbot/carbon\": \"^2.23.0\"\n    },\n    \"autoload\": {\n        \"files\": [\n            \"src/Collect/Support/helpers.php\",\n            \"src/Collect/Support/alias.php\"\n        ],\n        \"psr-4\": {\n            \"Tightenco\\\\Collect\\\\\": \"src/Collect\"\n        }\n    },\n    \"autoload-dev\": {\n        \"files\": [\n            \"tests/files/Support/Carbon.php\",\n            \"tests/files/Support/HtmlString.php\",\n            \"tests/files/Support/HigherOrderTapProxy.php\",\n            \"tests/files/Support/Str.php\",\n            \"tests/files/Support/Traits/Conditionable.php\",\n            \"tests/files/Support/Stringable.php\",\n            \"tests/files/Support/ItemNotFoundException.php\",\n            \"tests/files/Support/MultipleItemsFoundException.php\",\n            \"tests/Support/Concerns/CountsEnumerations.php\"\n        ]\n    },\n    \"scripts\": {\n        \"test\": [\n            \"@composer install\",\n            \"phpunit\"\n        ]\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Contracts/Support/Arrayable.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Contracts\\Support;\n\ninterface Arrayable\n{\n    /**\n     * Get the instance as an array.\n     *\n     * @return array\n     */\n    public function toArray();\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Contracts/Support/CanBeEscapedWhenCastToString.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Contracts\\Support;\n\ninterface CanBeEscapedWhenCastToString\n{\n    /**\n     * Indicate that the object's string representation should be escaped when __toString is invoked.\n     *\n     * @param  bool  $escape\n     * @return $this\n     */\n    public function escapeWhenCastingToString($escape = true);\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Contracts/Support/Htmlable.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Contracts\\Support;\n\ninterface Htmlable\n{\n    /**\n     * Get content as a string of HTML.\n     *\n     * @return string\n     */\n    public function toHtml();\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Contracts/Support/Jsonable.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Contracts\\Support;\n\ninterface Jsonable\n{\n    /**\n     * Convert the object to its JSON representation.\n     *\n     * @param  int  $options\n     * @return string\n     */\n    public function toJson($options = 0);\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/Arr.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support;\n\nuse ArrayAccess;\nuse Tightenco\\Collect\\Support\\Traits\\Macroable;\nuse InvalidArgumentException;\n\nclass Arr\n{\n    use Macroable;\n\n    /**\n     * Determine whether the given value is array accessible.\n     *\n     * @param  mixed  $value\n     * @return bool\n     */\n    public static function accessible($value)\n    {\n        return is_array($value) || $value instanceof ArrayAccess;\n    }\n\n    /**\n     * Add an element to an array using \"dot\" notation if it doesn't exist.\n     *\n     * @param  array  $array\n     * @param  string  $key\n     * @param  mixed  $value\n     * @return array\n     */\n    public static function add($array, $key, $value)\n    {\n        if (is_null(static::get($array, $key))) {\n            static::set($array, $key, $value);\n        }\n\n        return $array;\n    }\n\n    /**\n     * Collapse an array of arrays into a single array.\n     *\n     * @param  iterable  $array\n     * @return array\n     */\n    public static function collapse($array)\n    {\n        $results = [];\n\n        foreach ($array as $values) {\n            if ($values instanceof Collection) {\n                $values = $values->all();\n            } elseif (! is_array($values)) {\n                continue;\n            }\n\n            $results[] = $values;\n        }\n\n        return array_merge([], ...$results);\n    }\n\n    /**\n     * Cross join the given arrays, returning all possible permutations.\n     *\n     * @param  iterable  ...$arrays\n     * @return array\n     */\n    public static function crossJoin(...$arrays)\n    {\n        $results = [[]];\n\n        foreach ($arrays as $index => $array) {\n            $append = [];\n\n            foreach ($results as $product) {\n                foreach ($array as $item) {\n                    $product[$index] = $item;\n\n                    $append[] = $product;\n                }\n            }\n\n            $results = $append;\n        }\n\n        return $results;\n    }\n\n    /**\n     * Divide an array into two arrays. One with keys and the other with values.\n     *\n     * @param  array  $array\n     * @return array\n     */\n    public static function divide($array)\n    {\n        return [array_keys($array), array_values($array)];\n    }\n\n    /**\n     * Flatten a multi-dimensional associative array with dots.\n     *\n     * @param  iterable  $array\n     * @param  string  $prepend\n     * @return array\n     */\n    public static function dot($array, $prepend = '')\n    {\n        $results = [];\n\n        foreach ($array as $key => $value) {\n            if (is_array($value) && ! empty($value)) {\n                $results = array_merge($results, static::dot($value, $prepend.$key.'.'));\n            } else {\n                $results[$prepend.$key] = $value;\n            }\n        }\n\n        return $results;\n    }\n\n    /**\n     * Convert a flatten \"dot\" notation array into an expanded array.\n     *\n     * @param  iterable  $array\n     * @return array\n     */\n    public static function undot($array)\n    {\n        $results = [];\n\n        foreach ($array as $key => $value) {\n            static::set($results, $key, $value);\n        }\n\n        return $results;\n    }\n\n    /**\n     * Get all of the given array except for a specified array of keys.\n     *\n     * @param  array  $array\n     * @param  array|string  $keys\n     * @return array\n     */\n    public static function except($array, $keys)\n    {\n        static::forget($array, $keys);\n\n        return $array;\n    }\n\n    /**\n     * Determine if the given key exists in the provided array.\n     *\n     * @param  \\ArrayAccess|array  $array\n     * @param  string|int  $key\n     * @return bool\n     */\n    public static function exists($array, $key)\n    {\n        if ($array instanceof Enumerable) {\n            return $array->has($key);\n        }\n\n        if ($array instanceof ArrayAccess) {\n            return $array->offsetExists($key);\n        }\n\n        return array_key_exists($key, $array);\n    }\n\n    /**\n     * Return the first element in an array passing a given truth test.\n     *\n     * @param  iterable  $array\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public static function first($array, callable $callback = null, $default = null)\n    {\n        if (is_null($callback)) {\n            if (empty($array)) {\n                return value($default);\n            }\n\n            foreach ($array as $item) {\n                return $item;\n            }\n        }\n\n        foreach ($array as $key => $value) {\n            if ($callback($value, $key)) {\n                return $value;\n            }\n        }\n\n        return value($default);\n    }\n\n    /**\n     * Return the last element in an array passing a given truth test.\n     *\n     * @param  array  $array\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public static function last($array, callable $callback = null, $default = null)\n    {\n        if (is_null($callback)) {\n            return empty($array) ? value($default) : end($array);\n        }\n\n        return static::first(array_reverse($array, true), $callback, $default);\n    }\n\n    /**\n     * Flatten a multi-dimensional array into a single level.\n     *\n     * @param  iterable  $array\n     * @param  int  $depth\n     * @return array\n     */\n    public static function flatten($array, $depth = INF)\n    {\n        $result = [];\n\n        foreach ($array as $item) {\n            $item = $item instanceof Collection ? $item->all() : $item;\n\n            if (! is_array($item)) {\n                $result[] = $item;\n            } else {\n                $values = $depth === 1\n                    ? array_values($item)\n                    : static::flatten($item, $depth - 1);\n\n                foreach ($values as $value) {\n                    $result[] = $value;\n                }\n            }\n        }\n\n        return $result;\n    }\n\n    /**\n     * Remove one or many array items from a given array using \"dot\" notation.\n     *\n     * @param  array  $array\n     * @param  array|string  $keys\n     * @return void\n     */\n    public static function forget(&$array, $keys)\n    {\n        $original = &$array;\n\n        $keys = (array) $keys;\n\n        if (count($keys) === 0) {\n            return;\n        }\n\n        foreach ($keys as $key) {\n            // if the exact key exists in the top-level, remove it\n            if (static::exists($array, $key)) {\n                unset($array[$key]);\n\n                continue;\n            }\n\n            $parts = explode('.', $key);\n\n            // clean up before each pass\n            $array = &$original;\n\n            while (count($parts) > 1) {\n                $part = array_shift($parts);\n\n                if (isset($array[$part]) && is_array($array[$part])) {\n                    $array = &$array[$part];\n                } else {\n                    continue 2;\n                }\n            }\n\n            unset($array[array_shift($parts)]);\n        }\n    }\n\n    /**\n     * Get an item from an array using \"dot\" notation.\n     *\n     * @param  \\ArrayAccess|array  $array\n     * @param  string|int|null  $key\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public static function get($array, $key, $default = null)\n    {\n        if (! static::accessible($array)) {\n            return value($default);\n        }\n\n        if (is_null($key)) {\n            return $array;\n        }\n\n        if (static::exists($array, $key)) {\n            return $array[$key];\n        }\n\n        if (strpos($key, '.') === false) {\n            return $array[$key] ?? value($default);\n        }\n\n        foreach (explode('.', $key) as $segment) {\n            if (static::accessible($array) && static::exists($array, $segment)) {\n                $array = $array[$segment];\n            } else {\n                return value($default);\n            }\n        }\n\n        return $array;\n    }\n\n    /**\n     * Check if an item or items exist in an array using \"dot\" notation.\n     *\n     * @param  \\ArrayAccess|array  $array\n     * @param  string|array  $keys\n     * @return bool\n     */\n    public static function has($array, $keys)\n    {\n        $keys = (array) $keys;\n\n        if (! $array || $keys === []) {\n            return false;\n        }\n\n        foreach ($keys as $key) {\n            $subKeyArray = $array;\n\n            if (static::exists($array, $key)) {\n                continue;\n            }\n\n            foreach (explode('.', $key) as $segment) {\n                if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {\n                    $subKeyArray = $subKeyArray[$segment];\n                } else {\n                    return false;\n                }\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Determine if any of the keys exist in an array using \"dot\" notation.\n     *\n     * @param  \\ArrayAccess|array  $array\n     * @param  string|array  $keys\n     * @return bool\n     */\n    public static function hasAny($array, $keys)\n    {\n        if (is_null($keys)) {\n            return false;\n        }\n\n        $keys = (array) $keys;\n\n        if (! $array) {\n            return false;\n        }\n\n        if ($keys === []) {\n            return false;\n        }\n\n        foreach ($keys as $key) {\n            if (static::has($array, $key)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Determines if an array is associative.\n     *\n     * An array is \"associative\" if it doesn't have sequential numerical keys beginning with zero.\n     *\n     * @param  array  $array\n     * @return bool\n     */\n    public static function isAssoc(array $array)\n    {\n        $keys = array_keys($array);\n\n        return array_keys($keys) !== $keys;\n    }\n\n    /**\n     * Determines if an array is a list.\n     *\n     * An array is a \"list\" if all array keys are sequential integers starting from 0 with no gaps in between.\n     *\n     * @param  array  $array\n     * @return bool\n     */\n    public static function isList($array)\n    {\n        return ! self::isAssoc($array);\n    }\n\n    /**\n     * Get a subset of the items from the given array.\n     *\n     * @param  array  $array\n     * @param  array|string  $keys\n     * @return array\n     */\n    public static function only($array, $keys)\n    {\n        return array_intersect_key($array, array_flip((array) $keys));\n    }\n\n    /**\n     * Pluck an array of values from an array.\n     *\n     * @param  iterable  $array\n     * @param  string|array|int|null  $value\n     * @param  string|array|null  $key\n     * @return array\n     */\n    public static function pluck($array, $value, $key = null)\n    {\n        $results = [];\n\n        [$value, $key] = static::explodePluckParameters($value, $key);\n\n        foreach ($array as $item) {\n            $itemValue = data_get($item, $value);\n\n            // If the key is \"null\", we will just append the value to the array and keep\n            // looping. Otherwise we will key the array using the value of the key we\n            // received from the developer. Then we'll return the final array form.\n            if (is_null($key)) {\n                $results[] = $itemValue;\n            } else {\n                $itemKey = data_get($item, $key);\n\n                if (is_object($itemKey) && method_exists($itemKey, '__toString')) {\n                    $itemKey = (string) $itemKey;\n                }\n\n                $results[$itemKey] = $itemValue;\n            }\n        }\n\n        return $results;\n    }\n\n    /**\n     * Explode the \"value\" and \"key\" arguments passed to \"pluck\".\n     *\n     * @param  string|array  $value\n     * @param  string|array|null  $key\n     * @return array\n     */\n    protected static function explodePluckParameters($value, $key)\n    {\n        $value = is_string($value) ? explode('.', $value) : $value;\n\n        $key = is_null($key) || is_array($key) ? $key : explode('.', $key);\n\n        return [$value, $key];\n    }\n\n    /**\n     * Push an item onto the beginning of an array.\n     *\n     * @param  array  $array\n     * @param  mixed  $value\n     * @param  mixed  $key\n     * @return array\n     */\n    public static function prepend($array, $value, $key = null)\n    {\n        if (func_num_args() == 2) {\n            array_unshift($array, $value);\n        } else {\n            $array = [$key => $value] + $array;\n        }\n\n        return $array;\n    }\n\n    /**\n     * Get a value from the array, and remove it.\n     *\n     * @param  array  $array\n     * @param  string  $key\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public static function pull(&$array, $key, $default = null)\n    {\n        $value = static::get($array, $key, $default);\n\n        static::forget($array, $key);\n\n        return $value;\n    }\n\n    /**\n     * Convert the array into a query string.\n     *\n     * @param  array  $array\n     * @return string\n     */\n    public static function query($array)\n    {\n        return http_build_query($array, '', '&', PHP_QUERY_RFC3986);\n    }\n\n    /**\n     * Get one or a specified number of random values from an array.\n     *\n     * @param  array  $array\n     * @param  int|null  $number\n     * @param  bool|false  $preserveKeys\n     * @return mixed\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public static function random($array, $number = null, $preserveKeys = false)\n    {\n        $requested = is_null($number) ? 1 : $number;\n\n        $count = count($array);\n\n        if ($requested > $count) {\n            throw new InvalidArgumentException(\n                \"You requested {$requested} items, but there are only {$count} items available.\"\n            );\n        }\n\n        if (is_null($number)) {\n            return $array[array_rand($array)];\n        }\n\n        if ((int) $number === 0) {\n            return [];\n        }\n\n        $keys = array_rand($array, $number);\n\n        $results = [];\n\n        if ($preserveKeys) {\n            foreach ((array) $keys as $key) {\n                $results[$key] = $array[$key];\n            }\n        } else {\n            foreach ((array) $keys as $key) {\n                $results[] = $array[$key];\n            }\n        }\n\n        return $results;\n    }\n\n    /**\n     * Set an array item to a given value using \"dot\" notation.\n     *\n     * If no key is given to the method, the entire array will be replaced.\n     *\n     * @param  array  $array\n     * @param  string|null  $key\n     * @param  mixed  $value\n     * @return array\n     */\n    public static function set(&$array, $key, $value)\n    {\n        if (is_null($key)) {\n            return $array = $value;\n        }\n\n        $keys = explode('.', $key);\n\n        foreach ($keys as $i => $key) {\n            if (count($keys) === 1) {\n                break;\n            }\n\n            unset($keys[$i]);\n\n            // If the key doesn't exist at this depth, we will just create an empty array\n            // to hold the next value, allowing us to create the arrays to hold final\n            // values at the correct depth. Then we'll keep digging into the array.\n            if (! isset($array[$key]) || ! is_array($array[$key])) {\n                $array[$key] = [];\n            }\n\n            $array = &$array[$key];\n        }\n\n        $array[array_shift($keys)] = $value;\n\n        return $array;\n    }\n\n    /**\n     * Shuffle the given array and return the result.\n     *\n     * @param  array  $array\n     * @param  int|null  $seed\n     * @return array\n     */\n    public static function shuffle($array, $seed = null)\n    {\n        if (is_null($seed)) {\n            shuffle($array);\n        } else {\n            mt_srand($seed);\n            shuffle($array);\n            mt_srand();\n        }\n\n        return $array;\n    }\n\n    /**\n     * Sort the array using the given callback or \"dot\" notation.\n     *\n     * @param  array  $array\n     * @param  callable|array|string|null  $callback\n     * @return array\n     */\n    public static function sort($array, $callback = null)\n    {\n        return Collection::make($array)->sortBy($callback)->all();\n    }\n\n    /**\n     * Recursively sort an array by keys and values.\n     *\n     * @param  array  $array\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return array\n     */\n    public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false)\n    {\n        foreach ($array as &$value) {\n            if (is_array($value)) {\n                $value = static::sortRecursive($value, $options, $descending);\n            }\n        }\n\n        if (static::isAssoc($array)) {\n            $descending\n                    ? krsort($array, $options)\n                    : ksort($array, $options);\n        } else {\n            $descending\n                    ? rsort($array, $options)\n                    : sort($array, $options);\n        }\n\n        return $array;\n    }\n\n    /**\n     * Conditionally compile classes from an array into a CSS class list.\n     *\n     * @param  array  $array\n     * @return string\n     */\n    public static function toCssClasses($array)\n    {\n        $classList = static::wrap($array);\n\n        $classes = [];\n\n        foreach ($classList as $class => $constraint) {\n            if (is_numeric($class)) {\n                $classes[] = $constraint;\n            } elseif ($constraint) {\n                $classes[] = $class;\n            }\n        }\n\n        return implode(' ', $classes);\n    }\n\n    /**\n     * Filter the array using the given callback.\n     *\n     * @param  array  $array\n     * @param  callable  $callback\n     * @return array\n     */\n    public static function where($array, callable $callback)\n    {\n        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);\n    }\n\n    /**\n     * Filter items where the value is not null.\n     *\n     * @param  array  $array\n     * @return array\n     */\n    public static function whereNotNull($array)\n    {\n        return static::where($array, function ($value) {\n            return ! is_null($value);\n        });\n    }\n\n    /**\n     * If the given value is not an array and not null, wrap it in one.\n     *\n     * @param  mixed  $value\n     * @return array\n     */\n    public static function wrap($value)\n    {\n        if (is_null($value)) {\n            return [];\n        }\n\n        return is_array($value) ? $value : [$value];\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/Collection.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support;\n\nuse ArrayAccess;\nuse ArrayIterator;\nuse Tightenco\\Collect\\Contracts\\Support\\CanBeEscapedWhenCastToString;\nuse Tightenco\\Collect\\Support\\Traits\\EnumeratesValues;\nuse Tightenco\\Collect\\Support\\Traits\\Macroable;\nuse stdClass;\n\nclass Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerable\n{\n    use EnumeratesValues, Macroable;\n\n    /**\n     * The items contained in the collection.\n     *\n     * @var array\n     */\n    protected $items = [];\n\n    /**\n     * Create a new collection.\n     *\n     * @param  mixed  $items\n     * @return void\n     */\n    public function __construct($items = [])\n    {\n        $this->items = $this->getArrayableItems($items);\n    }\n\n    /**\n     * Create a collection with the given range.\n     *\n     * @param  int  $from\n     * @param  int  $to\n     * @return static\n     */\n    public static function range($from, $to)\n    {\n        return new static(range($from, $to));\n    }\n\n    /**\n     * Get all of the items in the collection.\n     *\n     * @return array\n     */\n    public function all()\n    {\n        return $this->items;\n    }\n\n    /**\n     * Get a lazy collection for the items in this collection.\n     *\n     * @return \\Tightenco\\Collect\\Support\\LazyCollection\n     */\n    public function lazy()\n    {\n        return new LazyCollection($this->items);\n    }\n\n    /**\n     * Get the average value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function avg($callback = null)\n    {\n        $callback = $this->valueRetriever($callback);\n\n        $items = $this->map(function ($value) use ($callback) {\n            return $callback($value);\n        })->filter(function ($value) {\n            return ! is_null($value);\n        });\n\n        if ($count = $items->count()) {\n            return $items->sum() / $count;\n        }\n    }\n\n    /**\n     * Get the median of a given key.\n     *\n     * @param  string|array|null  $key\n     * @return mixed\n     */\n    public function median($key = null)\n    {\n        $values = (isset($key) ? $this->pluck($key) : $this)\n            ->filter(function ($item) {\n                return ! is_null($item);\n            })->sort()->values();\n\n        $count = $values->count();\n\n        if ($count === 0) {\n            return;\n        }\n\n        $middle = (int) ($count / 2);\n\n        if ($count % 2) {\n            return $values->get($middle);\n        }\n\n        return (new static([\n            $values->get($middle - 1), $values->get($middle),\n        ]))->average();\n    }\n\n    /**\n     * Get the mode of a given key.\n     *\n     * @param  string|array|null  $key\n     * @return array|null\n     */\n    public function mode($key = null)\n    {\n        if ($this->count() === 0) {\n            return;\n        }\n\n        $collection = isset($key) ? $this->pluck($key) : $this;\n\n        $counts = new static;\n\n        $collection->each(function ($value) use ($counts) {\n            $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;\n        });\n\n        $sorted = $counts->sort();\n\n        $highestValue = $sorted->last();\n\n        return $sorted->filter(function ($value) use ($highestValue) {\n            return $value == $highestValue;\n        })->sort()->keys()->all();\n    }\n\n    /**\n     * Collapse the collection of items into a single array.\n     *\n     * @return static\n     */\n    public function collapse()\n    {\n        return new static(Arr::collapse($this->items));\n    }\n\n    /**\n     * Determine if an item exists in the collection.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function contains($key, $operator = null, $value = null)\n    {\n        if (func_num_args() === 1) {\n            if ($this->useAsCallable($key)) {\n                $placeholder = new stdClass;\n\n                return $this->first($key, $placeholder) !== $placeholder;\n            }\n\n            return in_array($key, $this->items);\n        }\n\n        return $this->contains($this->operatorForWhere(...func_get_args()));\n    }\n\n    /**\n     * Determine if an item is not contained in the collection.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function doesntContain($key, $operator = null, $value = null)\n    {\n        return ! $this->contains(...func_get_args());\n    }\n\n    /**\n     * Cross join with the given lists, returning all possible permutations.\n     *\n     * @param  mixed  ...$lists\n     * @return static\n     */\n    public function crossJoin(...$lists)\n    {\n        return new static(Arr::crossJoin(\n            $this->items, ...array_map([$this, 'getArrayableItems'], $lists)\n        ));\n    }\n\n    /**\n     * Get the items in the collection that are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diff($items)\n    {\n        return new static(array_diff($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Get the items in the collection that are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffUsing($items, callable $callback)\n    {\n        return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));\n    }\n\n    /**\n     * Get the items in the collection whose keys and values are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diffAssoc($items)\n    {\n        return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Get the items in the collection whose keys and values are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffAssocUsing($items, callable $callback)\n    {\n        return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));\n    }\n\n    /**\n     * Get the items in the collection whose keys are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diffKeys($items)\n    {\n        return new static(array_diff_key($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Get the items in the collection whose keys are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffKeysUsing($items, callable $callback)\n    {\n        return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));\n    }\n\n    /**\n     * Retrieve duplicate items from the collection.\n     *\n     * @param  callable|string|null  $callback\n     * @param  bool  $strict\n     * @return static\n     */\n    public function duplicates($callback = null, $strict = false)\n    {\n        $items = $this->map($this->valueRetriever($callback));\n\n        $uniqueItems = $items->unique(null, $strict);\n\n        $compare = $this->duplicateComparator($strict);\n\n        $duplicates = new static;\n\n        foreach ($items as $key => $value) {\n            if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {\n                $uniqueItems->shift();\n            } else {\n                $duplicates[$key] = $value;\n            }\n        }\n\n        return $duplicates;\n    }\n\n    /**\n     * Retrieve duplicate items from the collection using strict comparison.\n     *\n     * @param  callable|string|null  $callback\n     * @return static\n     */\n    public function duplicatesStrict($callback = null)\n    {\n        return $this->duplicates($callback, true);\n    }\n\n    /**\n     * Get the comparison function to detect duplicates.\n     *\n     * @param  bool  $strict\n     * @return \\Closure\n     */\n    protected function duplicateComparator($strict)\n    {\n        if ($strict) {\n            return function ($a, $b) {\n                return $a === $b;\n            };\n        }\n\n        return function ($a, $b) {\n            return $a == $b;\n        };\n    }\n\n    /**\n     * Get all items except for those with the specified keys.\n     *\n     * @param  \\Tightenco\\Collect\\Support\\Collection|mixed  $keys\n     * @return static\n     */\n    public function except($keys)\n    {\n        if ($keys instanceof Enumerable) {\n            $keys = $keys->all();\n        } elseif (! is_array($keys)) {\n            $keys = func_get_args();\n        }\n\n        return new static(Arr::except($this->items, $keys));\n    }\n\n    /**\n     * Run a filter over each of the items.\n     *\n     * @param  callable|null  $callback\n     * @return static\n     */\n    public function filter(callable $callback = null)\n    {\n        if ($callback) {\n            return new static(Arr::where($this->items, $callback));\n        }\n\n        return new static(array_filter($this->items));\n    }\n\n    /**\n     * Get the first item from the collection passing the given truth test.\n     *\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function first(callable $callback = null, $default = null)\n    {\n        return Arr::first($this->items, $callback, $default);\n    }\n\n    /**\n     * Get a flattened array of the items in the collection.\n     *\n     * @param  int  $depth\n     * @return static\n     */\n    public function flatten($depth = INF)\n    {\n        return new static(Arr::flatten($this->items, $depth));\n    }\n\n    /**\n     * Flip the items in the collection.\n     *\n     * @return static\n     */\n    public function flip()\n    {\n        return new static(array_flip($this->items));\n    }\n\n    /**\n     * Remove an item from the collection by key.\n     *\n     * @param  string|array  $keys\n     * @return $this\n     */\n    public function forget($keys)\n    {\n        foreach ((array) $keys as $key) {\n            $this->offsetUnset($key);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get an item from the collection by key.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function get($key, $default = null)\n    {\n        if (array_key_exists($key, $this->items)) {\n            return $this->items[$key];\n        }\n\n        return value($default);\n    }\n\n    /**\n     * Group an associative array by a field or using a callback.\n     *\n     * @param  array|callable|string  $groupBy\n     * @param  bool  $preserveKeys\n     * @return static\n     */\n    public function groupBy($groupBy, $preserveKeys = false)\n    {\n        if (! $this->useAsCallable($groupBy) && is_array($groupBy)) {\n            $nextGroups = $groupBy;\n\n            $groupBy = array_shift($nextGroups);\n        }\n\n        $groupBy = $this->valueRetriever($groupBy);\n\n        $results = [];\n\n        foreach ($this->items as $key => $value) {\n            $groupKeys = $groupBy($value, $key);\n\n            if (! is_array($groupKeys)) {\n                $groupKeys = [$groupKeys];\n            }\n\n            foreach ($groupKeys as $groupKey) {\n                $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;\n\n                if (! array_key_exists($groupKey, $results)) {\n                    $results[$groupKey] = new static;\n                }\n\n                $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);\n            }\n        }\n\n        $result = new static($results);\n\n        if (! empty($nextGroups)) {\n            return $result->map->groupBy($nextGroups, $preserveKeys);\n        }\n\n        return $result;\n    }\n\n    /**\n     * Key an associative array by a field or using a callback.\n     *\n     * @param  callable|string  $keyBy\n     * @return static\n     */\n    public function keyBy($keyBy)\n    {\n        $keyBy = $this->valueRetriever($keyBy);\n\n        $results = [];\n\n        foreach ($this->items as $key => $item) {\n            $resolvedKey = $keyBy($item, $key);\n\n            if (is_object($resolvedKey)) {\n                $resolvedKey = (string) $resolvedKey;\n            }\n\n            $results[$resolvedKey] = $item;\n        }\n\n        return new static($results);\n    }\n\n    /**\n     * Determine if an item exists in the collection by key.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    public function has($key)\n    {\n        $keys = is_array($key) ? $key : func_get_args();\n\n        foreach ($keys as $value) {\n            if (! array_key_exists($value, $this->items)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Determine if any of the keys exist in the collection.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    public function hasAny($key)\n    {\n        if ($this->isEmpty()) {\n            return false;\n        }\n\n        $keys = is_array($key) ? $key : func_get_args();\n\n        foreach ($keys as $value) {\n            if ($this->has($value)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Concatenate values of a given key as a string.\n     *\n     * @param  string  $value\n     * @param  string|null  $glue\n     * @return string\n     */\n    public function implode($value, $glue = null)\n    {\n        $first = $this->first();\n\n        if (is_array($first) || (is_object($first) && ! $first instanceof \\Illuminate\\Support\\Stringable)) {\n            return implode($glue ?? '', $this->pluck($value)->all());\n        }\n\n        return implode($value ?? '', $this->items);\n    }\n\n    /**\n     * Intersect the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function intersect($items)\n    {\n        return new static(array_intersect($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Intersect the collection with the given items by key.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function intersectByKeys($items)\n    {\n        return new static(array_intersect_key(\n            $this->items, $this->getArrayableItems($items)\n        ));\n    }\n\n    /**\n     * Determine if the collection is empty or not.\n     *\n     * @return bool\n     */\n    public function isEmpty()\n    {\n        return empty($this->items);\n    }\n\n    /**\n     * Determine if the collection contains a single item.\n     *\n     * @return bool\n     */\n    public function containsOneItem()\n    {\n        return $this->count() === 1;\n    }\n\n    /**\n     * Join all items from the collection using a string. The final items can use a separate glue string.\n     *\n     * @param  string  $glue\n     * @param  string  $finalGlue\n     * @return string\n     */\n    public function join($glue, $finalGlue = '')\n    {\n        if ($finalGlue === '') {\n            return $this->implode($glue);\n        }\n\n        $count = $this->count();\n\n        if ($count === 0) {\n            return '';\n        }\n\n        if ($count === 1) {\n            return $this->last();\n        }\n\n        $collection = new static($this->items);\n\n        $finalItem = $collection->pop();\n\n        return $collection->implode($glue).$finalGlue.$finalItem;\n    }\n\n    /**\n     * Get the keys of the collection items.\n     *\n     * @return static\n     */\n    public function keys()\n    {\n        return new static(array_keys($this->items));\n    }\n\n    /**\n     * Get the last item from the collection.\n     *\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function last(callable $callback = null, $default = null)\n    {\n        return Arr::last($this->items, $callback, $default);\n    }\n\n    /**\n     * Get the values of a given key.\n     *\n     * @param  string|array|int|null  $value\n     * @param  string|null  $key\n     * @return static\n     */\n    public function pluck($value, $key = null)\n    {\n        return new static(Arr::pluck($this->items, $value, $key));\n    }\n\n    /**\n     * Run a map over each of the items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function map(callable $callback)\n    {\n        $keys = array_keys($this->items);\n\n        $items = array_map($callback, $this->items, $keys);\n\n        return new static(array_combine($keys, $items));\n    }\n\n    /**\n     * Run a dictionary map over the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapToDictionary(callable $callback)\n    {\n        $dictionary = [];\n\n        foreach ($this->items as $key => $item) {\n            $pair = $callback($item, $key);\n\n            $key = key($pair);\n\n            $value = reset($pair);\n\n            if (! isset($dictionary[$key])) {\n                $dictionary[$key] = [];\n            }\n\n            $dictionary[$key][] = $value;\n        }\n\n        return new static($dictionary);\n    }\n\n    /**\n     * Run an associative map over each of the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapWithKeys(callable $callback)\n    {\n        $result = [];\n\n        foreach ($this->items as $key => $value) {\n            $assoc = $callback($value, $key);\n\n            foreach ($assoc as $mapKey => $mapValue) {\n                $result[$mapKey] = $mapValue;\n            }\n        }\n\n        return new static($result);\n    }\n\n    /**\n     * Merge the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function merge($items)\n    {\n        return new static(array_merge($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Recursively merge the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function mergeRecursive($items)\n    {\n        return new static(array_merge_recursive($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Create a collection by using this collection for keys and another for its values.\n     *\n     * @param  mixed  $values\n     * @return static\n     */\n    public function combine($values)\n    {\n        return new static(array_combine($this->all(), $this->getArrayableItems($values)));\n    }\n\n    /**\n     * Union the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function union($items)\n    {\n        return new static($this->items + $this->getArrayableItems($items));\n    }\n\n    /**\n     * Create a new collection consisting of every n-th element.\n     *\n     * @param  int  $step\n     * @param  int  $offset\n     * @return static\n     */\n    public function nth($step, $offset = 0)\n    {\n        $new = [];\n\n        $position = 0;\n\n        foreach ($this->items as $item) {\n            if ($position % $step === $offset) {\n                $new[] = $item;\n            }\n\n            $position++;\n        }\n\n        return new static($new);\n    }\n\n    /**\n     * Get the items with the specified keys.\n     *\n     * @param  mixed  $keys\n     * @return static\n     */\n    public function only($keys)\n    {\n        if (is_null($keys)) {\n            return new static($this->items);\n        }\n\n        if ($keys instanceof Enumerable) {\n            $keys = $keys->all();\n        }\n\n        $keys = is_array($keys) ? $keys : func_get_args();\n\n        return new static(Arr::only($this->items, $keys));\n    }\n\n    /**\n     * Get and remove the last N items from the collection.\n     *\n     * @param  int  $count\n     * @return mixed\n     */\n    public function pop($count = 1)\n    {\n        if ($count === 1) {\n            return array_pop($this->items);\n        }\n\n        if ($this->isEmpty()) {\n            return new static;\n        }\n\n        $results = [];\n\n        $collectionCount = $this->count();\n\n        foreach (range(1, min($count, $collectionCount)) as $item) {\n            array_push($results, array_pop($this->items));\n        }\n\n        return new static($results);\n    }\n\n    /**\n     * Push an item onto the beginning of the collection.\n     *\n     * @param  mixed  $value\n     * @param  mixed  $key\n     * @return $this\n     */\n    public function prepend($value, $key = null)\n    {\n        $this->items = Arr::prepend($this->items, ...func_get_args());\n\n        return $this;\n    }\n\n    /**\n     * Push one or more items onto the end of the collection.\n     *\n     * @param  mixed  $values\n     * @return $this\n     */\n    public function push(...$values)\n    {\n        foreach ($values as $value) {\n            $this->items[] = $value;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Push all of the given items onto the collection.\n     *\n     * @param  iterable  $source\n     * @return static\n     */\n    public function concat($source)\n    {\n        $result = new static($this);\n\n        foreach ($source as $item) {\n            $result->push($item);\n        }\n\n        return $result;\n    }\n\n    /**\n     * Get and remove an item from the collection.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function pull($key, $default = null)\n    {\n        return Arr::pull($this->items, $key, $default);\n    }\n\n    /**\n     * Put an item in the collection by key.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $value\n     * @return $this\n     */\n    public function put($key, $value)\n    {\n        $this->offsetSet($key, $value);\n\n        return $this;\n    }\n\n    /**\n     * Get one or a specified number of items randomly from the collection.\n     *\n     * @param  int|null  $number\n     * @return static|mixed\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public function random($number = null)\n    {\n        if (is_null($number)) {\n            return Arr::random($this->items);\n        }\n\n        return new static(Arr::random($this->items, $number));\n    }\n\n    /**\n     * Replace the collection items with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function replace($items)\n    {\n        return new static(array_replace($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Recursively replace the collection items with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function replaceRecursive($items)\n    {\n        return new static(array_replace_recursive($this->items, $this->getArrayableItems($items)));\n    }\n\n    /**\n     * Reverse items order.\n     *\n     * @return static\n     */\n    public function reverse()\n    {\n        return new static(array_reverse($this->items, true));\n    }\n\n    /**\n     * Search the collection for a given value and return the corresponding key if successful.\n     *\n     * @param  mixed  $value\n     * @param  bool  $strict\n     * @return mixed\n     */\n    public function search($value, $strict = false)\n    {\n        if (! $this->useAsCallable($value)) {\n            return array_search($value, $this->items, $strict);\n        }\n\n        foreach ($this->items as $key => $item) {\n            if ($value($item, $key)) {\n                return $key;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Get and remove the first N items from the collection.\n     *\n     * @param  int  $count\n     * @return mixed\n     */\n    public function shift($count = 1)\n    {\n        if ($count === 1) {\n            return array_shift($this->items);\n        }\n\n        if ($this->isEmpty()) {\n            return new static;\n        }\n\n        $results = [];\n\n        $collectionCount = $this->count();\n\n        foreach (range(1, min($count, $collectionCount)) as $item) {\n            array_push($results, array_shift($this->items));\n        }\n\n        return new static($results);\n    }\n\n    /**\n     * Shuffle the items in the collection.\n     *\n     * @param  int|null  $seed\n     * @return static\n     */\n    public function shuffle($seed = null)\n    {\n        return new static(Arr::shuffle($this->items, $seed));\n    }\n\n    /**\n     * Create chunks representing a \"sliding window\" view of the items in the collection.\n     *\n     * @param  int  $size\n     * @param  int  $step\n     * @return static\n     */\n    public function sliding($size = 2, $step = 1)\n    {\n        $chunks = floor(($this->count() - $size) / $step) + 1;\n\n        return static::times($chunks, function ($number) use ($size, $step) {\n            return $this->slice(($number - 1) * $step, $size);\n        });\n    }\n\n    /**\n     * Skip the first {$count} items.\n     *\n     * @param  int  $count\n     * @return static\n     */\n    public function skip($count)\n    {\n        return $this->slice($count);\n    }\n\n    /**\n     * Skip items in the collection until the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function skipUntil($value)\n    {\n        return new static($this->lazy()->skipUntil($value)->all());\n    }\n\n    /**\n     * Skip items in the collection while the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function skipWhile($value)\n    {\n        return new static($this->lazy()->skipWhile($value)->all());\n    }\n\n    /**\n     * Slice the underlying collection array.\n     *\n     * @param  int  $offset\n     * @param  int|null  $length\n     * @return static\n     */\n    public function slice($offset, $length = null)\n    {\n        return new static(array_slice($this->items, $offset, $length, true));\n    }\n\n    /**\n     * Split a collection into a certain number of groups.\n     *\n     * @param  int  $numberOfGroups\n     * @return static\n     */\n    public function split($numberOfGroups)\n    {\n        if ($this->isEmpty()) {\n            return new static;\n        }\n\n        $groups = new static;\n\n        $groupSize = floor($this->count() / $numberOfGroups);\n\n        $remain = $this->count() % $numberOfGroups;\n\n        $start = 0;\n\n        for ($i = 0; $i < $numberOfGroups; $i++) {\n            $size = $groupSize;\n\n            if ($i < $remain) {\n                $size++;\n            }\n\n            if ($size) {\n                $groups->push(new static(array_slice($this->items, $start, $size)));\n\n                $start += $size;\n            }\n        }\n\n        return $groups;\n    }\n\n    /**\n     * Split a collection into a certain number of groups, and fill the first groups completely.\n     *\n     * @param  int  $numberOfGroups\n     * @return static\n     */\n    public function splitIn($numberOfGroups)\n    {\n        return $this->chunk(ceil($this->count() / $numberOfGroups));\n    }\n\n    /**\n     * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return mixed\n     *\n     * @throws \\Tightenco\\Collect\\Support\\ItemNotFoundException\n     * @throws \\Tightenco\\Collect\\Support\\MultipleItemsFoundException\n     */\n    public function sole($key = null, $operator = null, $value = null)\n    {\n        $filter = func_num_args() > 1\n            ? $this->operatorForWhere(...func_get_args())\n            : $key;\n\n        $items = $this->when($filter)->filter($filter);\n\n        if ($items->isEmpty()) {\n            throw new ItemNotFoundException;\n        }\n\n        if ($items->count() > 1) {\n            throw new MultipleItemsFoundException;\n        }\n\n        return $items->first();\n    }\n\n    /**\n     * Get the first item in the collection but throw an exception if no matching items exist.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return mixed\n     *\n     * @throws \\Tightenco\\Collect\\Support\\ItemNotFoundException\n     */\n    public function firstOrFail($key = null, $operator = null, $value = null)\n    {\n        $filter = func_num_args() > 1\n            ? $this->operatorForWhere(...func_get_args())\n            : $key;\n\n        $placeholder = new stdClass();\n\n        $item = $this->first($filter, $placeholder);\n\n        if ($item === $placeholder) {\n            throw new ItemNotFoundException;\n        }\n\n        return $item;\n    }\n\n    /**\n     * Chunk the collection into chunks of the given size.\n     *\n     * @param  int  $size\n     * @return static\n     */\n    public function chunk($size)\n    {\n        if ($size <= 0) {\n            return new static;\n        }\n\n        $chunks = [];\n\n        foreach (array_chunk($this->items, $size, true) as $chunk) {\n            $chunks[] = new static($chunk);\n        }\n\n        return new static($chunks);\n    }\n\n    /**\n     * Chunk the collection into chunks with a callback.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function chunkWhile(callable $callback)\n    {\n        return new static(\n            $this->lazy()->chunkWhile($callback)->mapInto(static::class)\n        );\n    }\n\n    /**\n     * Sort through each item with a callback.\n     *\n     * @param  callable|int|null  $callback\n     * @return static\n     */\n    public function sort($callback = null)\n    {\n        $items = $this->items;\n\n        $callback && is_callable($callback)\n            ? uasort($items, $callback)\n            : asort($items, $callback ?? SORT_REGULAR);\n\n        return new static($items);\n    }\n\n    /**\n     * Sort items in descending order.\n     *\n     * @param  int  $options\n     * @return static\n     */\n    public function sortDesc($options = SORT_REGULAR)\n    {\n        $items = $this->items;\n\n        arsort($items, $options);\n\n        return new static($items);\n    }\n\n    /**\n     * Sort the collection using the given callback.\n     *\n     * @param  callable|array|string  $callback\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return static\n     */\n    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)\n    {\n        if (is_array($callback) && ! is_callable($callback)) {\n            return $this->sortByMany($callback);\n        }\n\n        $results = [];\n\n        $callback = $this->valueRetriever($callback);\n\n        // First we will loop through the items and get the comparator from a callback\n        // function which we were given. Then, we will sort the returned values and\n        // and grab the corresponding values for the sorted keys from this array.\n        foreach ($this->items as $key => $value) {\n            $results[$key] = $callback($value, $key);\n        }\n\n        $descending ? arsort($results, $options)\n            : asort($results, $options);\n\n        // Once we have sorted all of the keys in the array, we will loop through them\n        // and grab the corresponding model so we can set the underlying items list\n        // to the sorted version. Then we'll just return the collection instance.\n        foreach (array_keys($results) as $key) {\n            $results[$key] = $this->items[$key];\n        }\n\n        return new static($results);\n    }\n\n    /**\n     * Sort the collection using multiple comparisons.\n     *\n     * @param  array  $comparisons\n     * @return static\n     */\n    protected function sortByMany(array $comparisons = [])\n    {\n        $items = $this->items;\n\n        usort($items, function ($a, $b) use ($comparisons) {\n            foreach ($comparisons as $comparison) {\n                $comparison = Arr::wrap($comparison);\n\n                $prop = $comparison[0];\n\n                $ascending = Arr::get($comparison, 1, true) === true ||\n                             Arr::get($comparison, 1, true) === 'asc';\n\n                $result = 0;\n\n                if (! is_string($prop) && is_callable($prop)) {\n                    $result = $prop($a, $b);\n                } else {\n                    $values = [data_get($a, $prop), data_get($b, $prop)];\n\n                    if (! $ascending) {\n                        $values = array_reverse($values);\n                    }\n\n                    $result = $values[0] <=> $values[1];\n                }\n\n                if ($result === 0) {\n                    continue;\n                }\n\n                return $result;\n            }\n        });\n\n        return new static($items);\n    }\n\n    /**\n     * Sort the collection in descending order using the given callback.\n     *\n     * @param  callable|string  $callback\n     * @param  int  $options\n     * @return static\n     */\n    public function sortByDesc($callback, $options = SORT_REGULAR)\n    {\n        return $this->sortBy($callback, $options, true);\n    }\n\n    /**\n     * Sort the collection keys.\n     *\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return static\n     */\n    public function sortKeys($options = SORT_REGULAR, $descending = false)\n    {\n        $items = $this->items;\n\n        $descending ? krsort($items, $options) : ksort($items, $options);\n\n        return new static($items);\n    }\n\n    /**\n     * Sort the collection keys in descending order.\n     *\n     * @param  int  $options\n     * @return static\n     */\n    public function sortKeysDesc($options = SORT_REGULAR)\n    {\n        return $this->sortKeys($options, true);\n    }\n\n    /**\n     * Splice a portion of the underlying collection array.\n     *\n     * @param  int  $offset\n     * @param  int|null  $length\n     * @param  mixed  $replacement\n     * @return static\n     */\n    public function splice($offset, $length = null, $replacement = [])\n    {\n        if (func_num_args() === 1) {\n            return new static(array_splice($this->items, $offset));\n        }\n\n        return new static(array_splice($this->items, $offset, $length, $this->getArrayableItems($replacement)));\n    }\n\n    /**\n     * Take the first or last {$limit} items.\n     *\n     * @param  int  $limit\n     * @return static\n     */\n    public function take($limit)\n    {\n        if ($limit < 0) {\n            return $this->slice($limit, abs($limit));\n        }\n\n        return $this->slice(0, $limit);\n    }\n\n    /**\n     * Take items in the collection until the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function takeUntil($value)\n    {\n        return new static($this->lazy()->takeUntil($value)->all());\n    }\n\n    /**\n     * Take items in the collection while the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function takeWhile($value)\n    {\n        return new static($this->lazy()->takeWhile($value)->all());\n    }\n\n    /**\n     * Transform each item in the collection using a callback.\n     *\n     * @param  callable  $callback\n     * @return $this\n     */\n    public function transform(callable $callback)\n    {\n        $this->items = $this->map($callback)->all();\n\n        return $this;\n    }\n\n    /**\n     * Convert a flatten \"dot\" notation array into an expanded array.\n     *\n     * @return static\n     */\n    public function undot()\n    {\n        return new static(Arr::undot($this->all()));\n    }\n\n    /**\n     * Return only unique items from the collection array.\n     *\n     * @param  string|callable|null  $key\n     * @param  bool  $strict\n     * @return static\n     */\n    public function unique($key = null, $strict = false)\n    {\n        if (is_null($key) && $strict === false) {\n            return new static(array_unique($this->items, SORT_REGULAR));\n        }\n\n        $callback = $this->valueRetriever($key);\n\n        $exists = [];\n\n        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {\n            if (in_array($id = $callback($item, $key), $exists, $strict)) {\n                return true;\n            }\n\n            $exists[] = $id;\n        });\n    }\n\n    /**\n     * Reset the keys on the underlying array.\n     *\n     * @return static\n     */\n    public function values()\n    {\n        return new static(array_values($this->items));\n    }\n\n    /**\n     * Zip the collection together with one or more arrays.\n     *\n     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);\n     *      => [[1, 4], [2, 5], [3, 6]]\n     *\n     * @param  mixed  ...$items\n     * @return static\n     */\n    public function zip($items)\n    {\n        $arrayableItems = array_map(function ($items) {\n            return $this->getArrayableItems($items);\n        }, func_get_args());\n\n        $params = array_merge([function () {\n            return new static(func_get_args());\n        }, $this->items], $arrayableItems);\n\n        return new static(array_map(...$params));\n    }\n\n    /**\n     * Pad collection to the specified length with a value.\n     *\n     * @param  int  $size\n     * @param  mixed  $value\n     * @return static\n     */\n    public function pad($size, $value)\n    {\n        return new static(array_pad($this->items, $size, $value));\n    }\n\n    /**\n     * Get an iterator for the items.\n     *\n     * @return \\ArrayIterator\n     */\n    #[\\ReturnTypeWillChange]\n    public function getIterator()\n    {\n        return new ArrayIterator($this->items);\n    }\n\n    /**\n     * Count the number of items in the collection.\n     *\n     * @return int\n     */\n    #[\\ReturnTypeWillChange]\n    public function count()\n    {\n        return count($this->items);\n    }\n\n    /**\n     * Count the number of items in the collection by a field or using a callback.\n     *\n     * @param  callable|string  $countBy\n     * @return static\n     */\n    public function countBy($countBy = null)\n    {\n        return new static($this->lazy()->countBy($countBy)->all());\n    }\n\n    /**\n     * Add an item to the collection.\n     *\n     * @param  mixed  $item\n     * @return $this\n     */\n    public function add($item)\n    {\n        $this->items[] = $item;\n\n        return $this;\n    }\n\n    /**\n     * Get a base Support collection instance from this collection.\n     *\n     * @return \\Tightenco\\Collect\\Support\\Collection\n     */\n    public function toBase()\n    {\n        return new self($this);\n    }\n\n    /**\n     * Determine if an item exists at an offset.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetExists($key)\n    {\n        return isset($this->items[$key]);\n    }\n\n    /**\n     * Get an item at a given offset.\n     *\n     * @param  mixed  $key\n     * @return mixed\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetGet($key)\n    {\n        return $this->items[$key];\n    }\n\n    /**\n     * Set the item at a given offset.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $value\n     * @return void\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetSet($key, $value)\n    {\n        if (is_null($key)) {\n            $this->items[] = $value;\n        } else {\n            $this->items[$key] = $value;\n        }\n    }\n\n    /**\n     * Unset the item at a given offset.\n     *\n     * @param  string  $key\n     * @return void\n     */\n    #[\\ReturnTypeWillChange]\n    public function offsetUnset($key)\n    {\n        unset($this->items[$key]);\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/Enumerable.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support;\n\nuse Countable;\nuse Tightenco\\Collect\\Contracts\\Support\\Arrayable;\nuse Tightenco\\Collect\\Contracts\\Support\\Jsonable;\nuse IteratorAggregate;\nuse JsonSerializable;\n\ninterface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable\n{\n    /**\n     * Create a new collection instance if the value isn't one already.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public static function make($items = []);\n\n    /**\n     * Create a new instance by invoking the callback a given amount of times.\n     *\n     * @param  int  $number\n     * @param  callable|null  $callback\n     * @return static\n     */\n    public static function times($number, callable $callback = null);\n\n    /**\n     * Create a collection with the given range.\n     *\n     * @param  int  $from\n     * @param  int  $to\n     * @return static\n     */\n    public static function range($from, $to);\n\n    /**\n     * Wrap the given value in a collection if applicable.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public static function wrap($value);\n\n    /**\n     * Get the underlying items from the given collection if applicable.\n     *\n     * @param  array|static  $value\n     * @return array\n     */\n    public static function unwrap($value);\n\n    /**\n     * Create a new instance with no items.\n     *\n     * @return static\n     */\n    public static function empty();\n\n    /**\n     * Get all items in the enumerable.\n     *\n     * @return array\n     */\n    public function all();\n\n    /**\n     * Alias for the \"avg\" method.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function average($callback = null);\n\n    /**\n     * Get the median of a given key.\n     *\n     * @param  string|array|null  $key\n     * @return mixed\n     */\n    public function median($key = null);\n\n    /**\n     * Get the mode of a given key.\n     *\n     * @param  string|array|null  $key\n     * @return array|null\n     */\n    public function mode($key = null);\n\n    /**\n     * Collapse the items into a single enumerable.\n     *\n     * @return static\n     */\n    public function collapse();\n\n    /**\n     * Alias for the \"contains\" method.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function some($key, $operator = null, $value = null);\n\n    /**\n     * Determine if an item exists, using strict comparison.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function containsStrict($key, $value = null);\n\n    /**\n     * Get the average value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function avg($callback = null);\n\n    /**\n     * Determine if an item exists in the enumerable.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function contains($key, $operator = null, $value = null);\n\n    /**\n     * Cross join with the given lists, returning all possible permutations.\n     *\n     * @param  mixed  ...$lists\n     * @return static\n     */\n    public function crossJoin(...$lists);\n\n    /**\n     * Dump the collection and end the script.\n     *\n     * @param  mixed  ...$args\n     * @return void\n     */\n    public function dd(...$args);\n\n    /**\n     * Dump the collection.\n     *\n     * @return $this\n     */\n    public function dump();\n\n    /**\n     * Get the items that are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diff($items);\n\n    /**\n     * Get the items that are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffUsing($items, callable $callback);\n\n    /**\n     * Get the items whose keys and values are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diffAssoc($items);\n\n    /**\n     * Get the items whose keys and values are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffAssocUsing($items, callable $callback);\n\n    /**\n     * Get the items whose keys are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diffKeys($items);\n\n    /**\n     * Get the items whose keys are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffKeysUsing($items, callable $callback);\n\n    /**\n     * Retrieve duplicate items.\n     *\n     * @param  callable|string|null  $callback\n     * @param  bool  $strict\n     * @return static\n     */\n    public function duplicates($callback = null, $strict = false);\n\n    /**\n     * Retrieve duplicate items using strict comparison.\n     *\n     * @param  callable|string|null  $callback\n     * @return static\n     */\n    public function duplicatesStrict($callback = null);\n\n    /**\n     * Execute a callback over each item.\n     *\n     * @param  callable  $callback\n     * @return $this\n     */\n    public function each(callable $callback);\n\n    /**\n     * Execute a callback over each nested chunk of items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function eachSpread(callable $callback);\n\n    /**\n     * Determine if all items pass the given truth test.\n     *\n     * @param  string|callable  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function every($key, $operator = null, $value = null);\n\n    /**\n     * Get all items except for those with the specified keys.\n     *\n     * @param  mixed  $keys\n     * @return static\n     */\n    public function except($keys);\n\n    /**\n     * Run a filter over each of the items.\n     *\n     * @param  callable|null  $callback\n     * @return static\n     */\n    public function filter(callable $callback = null);\n\n    /**\n     * Apply the callback if the value is truthy.\n     *\n     * @param  bool  $value\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function when($value, callable $callback, callable $default = null);\n\n    /**\n     * Apply the callback if the collection is empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function whenEmpty(callable $callback, callable $default = null);\n\n    /**\n     * Apply the callback if the collection is not empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function whenNotEmpty(callable $callback, callable $default = null);\n\n    /**\n     * Apply the callback if the value is falsy.\n     *\n     * @param  bool  $value\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function unless($value, callable $callback, callable $default = null);\n\n    /**\n     * Apply the callback unless the collection is empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function unlessEmpty(callable $callback, callable $default = null);\n\n    /**\n     * Apply the callback unless the collection is not empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function unlessNotEmpty(callable $callback, callable $default = null);\n\n    /**\n     * Filter items by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return static\n     */\n    public function where($key, $operator = null, $value = null);\n\n    /**\n     * Filter items where the value for the given key is null.\n     *\n     * @param  string|null  $key\n     * @return static\n     */\n    public function whereNull($key = null);\n\n    /**\n     * Filter items where the value for the given key is not null.\n     *\n     * @param  string|null  $key\n     * @return static\n     */\n    public function whereNotNull($key = null);\n\n    /**\n     * Filter items by the given key value pair using strict comparison.\n     *\n     * @param  string  $key\n     * @param  mixed  $value\n     * @return static\n     */\n    public function whereStrict($key, $value);\n\n    /**\n     * Filter items by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @param  bool  $strict\n     * @return static\n     */\n    public function whereIn($key, $values, $strict = false);\n\n    /**\n     * Filter items by the given key value pair using strict comparison.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @return static\n     */\n    public function whereInStrict($key, $values);\n\n    /**\n     * Filter items such that the value of the given key is between the given values.\n     *\n     * @param  string  $key\n     * @param  array  $values\n     * @return static\n     */\n    public function whereBetween($key, $values);\n\n    /**\n     * Filter items such that the value of the given key is not between the given values.\n     *\n     * @param  string  $key\n     * @param  array  $values\n     * @return static\n     */\n    public function whereNotBetween($key, $values);\n\n    /**\n     * Filter items by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @param  bool  $strict\n     * @return static\n     */\n    public function whereNotIn($key, $values, $strict = false);\n\n    /**\n     * Filter items by the given key value pair using strict comparison.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @return static\n     */\n    public function whereNotInStrict($key, $values);\n\n    /**\n     * Filter the items, removing any items that don't match the given type(s).\n     *\n     * @param  string|string[]  $type\n     * @return static\n     */\n    public function whereInstanceOf($type);\n\n    /**\n     * Get the first item from the enumerable passing the given truth test.\n     *\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function first(callable $callback = null, $default = null);\n\n    /**\n     * Get the first item by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return mixed\n     */\n    public function firstWhere($key, $operator = null, $value = null);\n\n    /**\n     * Get a flattened array of the items in the collection.\n     *\n     * @param  int  $depth\n     * @return static\n     */\n    public function flatten($depth = INF);\n\n    /**\n     * Flip the values with their keys.\n     *\n     * @return static\n     */\n    public function flip();\n\n    /**\n     * Get an item from the collection by key.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function get($key, $default = null);\n\n    /**\n     * Group an associative array by a field or using a callback.\n     *\n     * @param  array|callable|string  $groupBy\n     * @param  bool  $preserveKeys\n     * @return static\n     */\n    public function groupBy($groupBy, $preserveKeys = false);\n\n    /**\n     * Key an associative array by a field or using a callback.\n     *\n     * @param  callable|string  $keyBy\n     * @return static\n     */\n    public function keyBy($keyBy);\n\n    /**\n     * Determine if an item exists in the collection by key.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    public function has($key);\n\n    /**\n     * Concatenate values of a given key as a string.\n     *\n     * @param  string  $value\n     * @param  string|null  $glue\n     * @return string\n     */\n    public function implode($value, $glue = null);\n\n    /**\n     * Intersect the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function intersect($items);\n\n    /**\n     * Intersect the collection with the given items by key.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function intersectByKeys($items);\n\n    /**\n     * Determine if the collection is empty or not.\n     *\n     * @return bool\n     */\n    public function isEmpty();\n\n    /**\n     * Determine if the collection is not empty.\n     *\n     * @return bool\n     */\n    public function isNotEmpty();\n\n    /**\n     * Join all items from the collection using a string. The final items can use a separate glue string.\n     *\n     * @param  string  $glue\n     * @param  string  $finalGlue\n     * @return string\n     */\n    public function join($glue, $finalGlue = '');\n\n    /**\n     * Get the keys of the collection items.\n     *\n     * @return static\n     */\n    public function keys();\n\n    /**\n     * Get the last item from the collection.\n     *\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function last(callable $callback = null, $default = null);\n\n    /**\n     * Run a map over each of the items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function map(callable $callback);\n\n    /**\n     * Run a map over each nested chunk of items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapSpread(callable $callback);\n\n    /**\n     * Run a dictionary map over the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapToDictionary(callable $callback);\n\n    /**\n     * Run a grouping map over the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapToGroups(callable $callback);\n\n    /**\n     * Run an associative map over each of the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapWithKeys(callable $callback);\n\n    /**\n     * Map a collection and flatten the result by a single level.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function flatMap(callable $callback);\n\n    /**\n     * Map the values into a new class.\n     *\n     * @param  string  $class\n     * @return static\n     */\n    public function mapInto($class);\n\n    /**\n     * Merge the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function merge($items);\n\n    /**\n     * Recursively merge the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function mergeRecursive($items);\n\n    /**\n     * Create a collection by using this collection for keys and another for its values.\n     *\n     * @param  mixed  $values\n     * @return static\n     */\n    public function combine($values);\n\n    /**\n     * Union the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function union($items);\n\n    /**\n     * Get the min value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function min($callback = null);\n\n    /**\n     * Get the max value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function max($callback = null);\n\n    /**\n     * Create a new collection consisting of every n-th element.\n     *\n     * @param  int  $step\n     * @param  int  $offset\n     * @return static\n     */\n    public function nth($step, $offset = 0);\n\n    /**\n     * Get the items with the specified keys.\n     *\n     * @param  mixed  $keys\n     * @return static\n     */\n    public function only($keys);\n\n    /**\n     * \"Paginate\" the collection by slicing it into a smaller collection.\n     *\n     * @param  int  $page\n     * @param  int  $perPage\n     * @return static\n     */\n    public function forPage($page, $perPage);\n\n    /**\n     * Partition the collection into two arrays using the given callback or key.\n     *\n     * @param  callable|string  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return static\n     */\n    public function partition($key, $operator = null, $value = null);\n\n    /**\n     * Push all of the given items onto the collection.\n     *\n     * @param  iterable  $source\n     * @return static\n     */\n    public function concat($source);\n\n    /**\n     * Get one or a specified number of items randomly from the collection.\n     *\n     * @param  int|null  $number\n     * @return static|mixed\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public function random($number = null);\n\n    /**\n     * Reduce the collection to a single value.\n     *\n     * @param  callable  $callback\n     * @param  mixed  $initial\n     * @return mixed\n     */\n    public function reduce(callable $callback, $initial = null);\n\n    /**\n     * Replace the collection items with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function replace($items);\n\n    /**\n     * Recursively replace the collection items with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function replaceRecursive($items);\n\n    /**\n     * Reverse items order.\n     *\n     * @return static\n     */\n    public function reverse();\n\n    /**\n     * Search the collection for a given value and return the corresponding key if successful.\n     *\n     * @param  mixed  $value\n     * @param  bool  $strict\n     * @return mixed\n     */\n    public function search($value, $strict = false);\n\n    /**\n     * Shuffle the items in the collection.\n     *\n     * @param  int|null  $seed\n     * @return static\n     */\n    public function shuffle($seed = null);\n\n    /**\n     * Skip the first {$count} items.\n     *\n     * @param  int  $count\n     * @return static\n     */\n    public function skip($count);\n\n    /**\n     * Skip items in the collection until the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function skipUntil($value);\n\n    /**\n     * Skip items in the collection while the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function skipWhile($value);\n\n    /**\n     * Get a slice of items from the enumerable.\n     *\n     * @param  int  $offset\n     * @param  int|null  $length\n     * @return static\n     */\n    public function slice($offset, $length = null);\n\n    /**\n     * Split a collection into a certain number of groups.\n     *\n     * @param  int  $numberOfGroups\n     * @return static\n     */\n    public function split($numberOfGroups);\n\n    /**\n     * Chunk the collection into chunks of the given size.\n     *\n     * @param  int  $size\n     * @return static\n     */\n    public function chunk($size);\n\n    /**\n     * Chunk the collection into chunks with a callback.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function chunkWhile(callable $callback);\n\n    /**\n     * Sort through each item with a callback.\n     *\n     * @param  callable|null|int  $callback\n     * @return static\n     */\n    public function sort($callback = null);\n\n    /**\n     * Sort items in descending order.\n     *\n     * @param  int  $options\n     * @return static\n     */\n    public function sortDesc($options = SORT_REGULAR);\n\n    /**\n     * Sort the collection using the given callback.\n     *\n     * @param  callable|string  $callback\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return static\n     */\n    public function sortBy($callback, $options = SORT_REGULAR, $descending = false);\n\n    /**\n     * Sort the collection in descending order using the given callback.\n     *\n     * @param  callable|string  $callback\n     * @param  int  $options\n     * @return static\n     */\n    public function sortByDesc($callback, $options = SORT_REGULAR);\n\n    /**\n     * Sort the collection keys.\n     *\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return static\n     */\n    public function sortKeys($options = SORT_REGULAR, $descending = false);\n\n    /**\n     * Sort the collection keys in descending order.\n     *\n     * @param  int  $options\n     * @return static\n     */\n    public function sortKeysDesc($options = SORT_REGULAR);\n\n    /**\n     * Get the sum of the given values.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function sum($callback = null);\n\n    /**\n     * Take the first or last {$limit} items.\n     *\n     * @param  int  $limit\n     * @return static\n     */\n    public function take($limit);\n\n    /**\n     * Take items in the collection until the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function takeUntil($value);\n\n    /**\n     * Take items in the collection while the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function takeWhile($value);\n\n    /**\n     * Pass the collection to the given callback and then return it.\n     *\n     * @param  callable  $callback\n     * @return $this\n     */\n    public function tap(callable $callback);\n\n    /**\n     * Pass the enumerable to the given callback and return the result.\n     *\n     * @param  callable  $callback\n     * @return mixed\n     */\n    public function pipe(callable $callback);\n\n    /**\n     * Get the values of a given key.\n     *\n     * @param  string|array  $value\n     * @param  string|null  $key\n     * @return static\n     */\n    public function pluck($value, $key = null);\n\n    /**\n     * Create a collection of all elements that do not pass a given truth test.\n     *\n     * @param  callable|mixed  $callback\n     * @return static\n     */\n    public function reject($callback = true);\n\n    /**\n     * Return only unique items from the collection array.\n     *\n     * @param  string|callable|null  $key\n     * @param  bool  $strict\n     * @return static\n     */\n    public function unique($key = null, $strict = false);\n\n    /**\n     * Return only unique items from the collection array using strict comparison.\n     *\n     * @param  string|callable|null  $key\n     * @return static\n     */\n    public function uniqueStrict($key = null);\n\n    /**\n     * Reset the keys on the underlying array.\n     *\n     * @return static\n     */\n    public function values();\n\n    /**\n     * Pad collection to the specified length with a value.\n     *\n     * @param  int  $size\n     * @param  mixed  $value\n     * @return static\n     */\n    public function pad($size, $value);\n\n    /**\n     * Count the number of items in the collection using a given truth test.\n     *\n     * @param  callable|null  $callback\n     * @return static\n     */\n    public function countBy($callback = null);\n\n    /**\n     * Zip the collection together with one or more arrays.\n     *\n     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);\n     *      => [[1, 4], [2, 5], [3, 6]]\n     *\n     * @param  mixed  ...$items\n     * @return static\n     */\n    public function zip($items);\n\n    /**\n     * Collect the values into a collection.\n     *\n     * @return \\Tightenco\\Collect\\Support\\Collection\n     */\n    public function collect();\n\n    /**\n     * Convert the collection to its string representation.\n     *\n     * @return string\n     */\n    public function __toString();\n\n    /**\n     * Add a method to the list of proxied methods.\n     *\n     * @param  string  $method\n     * @return void\n     */\n    public static function proxy($method);\n\n    /**\n     * Dynamically access collection proxies.\n     *\n     * @param  string  $key\n     * @return mixed\n     *\n     * @throws \\Exception\n     */\n    public function __get($key);\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/HigherOrderCollectionProxy.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support;\n\n/**\n * @mixin \\Tightenco\\Collect\\Support\\Enumerable\n */\nclass HigherOrderCollectionProxy\n{\n    /**\n     * The collection being operated on.\n     *\n     * @var \\Tightenco\\Collect\\Support\\Enumerable\n     */\n    protected $collection;\n\n    /**\n     * The method being proxied.\n     *\n     * @var string\n     */\n    protected $method;\n\n    /**\n     * Create a new proxy instance.\n     *\n     * @param  \\Tightenco\\Collect\\Support\\Enumerable  $collection\n     * @param  string  $method\n     * @return void\n     */\n    public function __construct(Enumerable $collection, $method)\n    {\n        $this->method = $method;\n        $this->collection = $collection;\n    }\n\n    /**\n     * Proxy accessing an attribute onto the collection items.\n     *\n     * @param  string  $key\n     * @return mixed\n     */\n    public function __get($key)\n    {\n        return $this->collection->{$this->method}(function ($value) use ($key) {\n            return is_array($value) ? $value[$key] : $value->{$key};\n        });\n    }\n\n    /**\n     * Proxy a method call onto the collection items.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {\n            return $value->{$method}(...$parameters);\n        });\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/HigherOrderWhenProxy.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support;\n\n/**\n * @mixin \\Tightenco\\Collect\\Support\\Enumerable\n */\nclass HigherOrderWhenProxy\n{\n    /**\n     * The collection being operated on.\n     *\n     * @var \\Tightenco\\Collect\\Support\\Enumerable\n     */\n    protected $collection;\n\n    /**\n     * The condition for proxying.\n     *\n     * @var bool\n     */\n    protected $condition;\n\n    /**\n     * Create a new proxy instance.\n     *\n     * @param  \\Tightenco\\Collect\\Support\\Enumerable  $collection\n     * @param  bool  $condition\n     * @return void\n     */\n    public function __construct(Enumerable $collection, $condition)\n    {\n        $this->condition = $condition;\n        $this->collection = $collection;\n    }\n\n    /**\n     * Proxy accessing an attribute onto the collection.\n     *\n     * @param  string  $key\n     * @return mixed\n     */\n    public function __get($key)\n    {\n        return $this->condition\n            ? $this->collection->{$key}\n            : $this->collection;\n    }\n\n    /**\n     * Proxy a method call onto the collection.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        return $this->condition\n            ? $this->collection->{$method}(...$parameters)\n            : $this->collection;\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/LazyCollection.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support;\n\nuse ArrayIterator;\nuse Closure;\nuse DateTimeInterface;\nuse Tightenco\\Collect\\Contracts\\Support\\CanBeEscapedWhenCastToString;\nuse Tightenco\\Collect\\Support\\Traits\\EnumeratesValues;\nuse Tightenco\\Collect\\Support\\Traits\\Macroable;\nuse IteratorAggregate;\nuse stdClass;\n\nclass LazyCollection implements CanBeEscapedWhenCastToString, Enumerable\n{\n    use EnumeratesValues, Macroable;\n\n    /**\n     * The source from which to generate items.\n     *\n     * @var callable|static\n     */\n    public $source;\n\n    /**\n     * Create a new lazy collection instance.\n     *\n     * @param  mixed  $source\n     * @return void\n     */\n    public function __construct($source = null)\n    {\n        if ($source instanceof Closure || $source instanceof self) {\n            $this->source = $source;\n        } elseif (is_null($source)) {\n            $this->source = static::empty();\n        } else {\n            $this->source = $this->getArrayableItems($source);\n        }\n    }\n\n    /**\n     * Create a collection with the given range.\n     *\n     * @param  int  $from\n     * @param  int  $to\n     * @return static\n     */\n    public static function range($from, $to)\n    {\n        return new static(function () use ($from, $to) {\n            if ($from <= $to) {\n                for (; $from <= $to; $from++) {\n                    yield $from;\n                }\n            } else {\n                for (; $from >= $to; $from--) {\n                    yield $from;\n                }\n            }\n        });\n    }\n\n    /**\n     * Get all items in the enumerable.\n     *\n     * @return array\n     */\n    public function all()\n    {\n        if (is_array($this->source)) {\n            return $this->source;\n        }\n\n        return iterator_to_array($this->getIterator());\n    }\n\n    /**\n     * Eager load all items into a new lazy collection backed by an array.\n     *\n     * @return static\n     */\n    public function eager()\n    {\n        return new static($this->all());\n    }\n\n    /**\n     * Cache values as they're enumerated.\n     *\n     * @return static\n     */\n    public function remember()\n    {\n        $iterator = $this->getIterator();\n\n        $iteratorIndex = 0;\n\n        $cache = [];\n\n        return new static(function () use ($iterator, &$iteratorIndex, &$cache) {\n            for ($index = 0; true; $index++) {\n                if (array_key_exists($index, $cache)) {\n                    yield $cache[$index][0] => $cache[$index][1];\n\n                    continue;\n                }\n\n                if ($iteratorIndex < $index) {\n                    $iterator->next();\n\n                    $iteratorIndex++;\n                }\n\n                if (! $iterator->valid()) {\n                    break;\n                }\n\n                $cache[$index] = [$iterator->key(), $iterator->current()];\n\n                yield $cache[$index][0] => $cache[$index][1];\n            }\n        });\n    }\n\n    /**\n     * Get the average value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function avg($callback = null)\n    {\n        return $this->collect()->avg($callback);\n    }\n\n    /**\n     * Get the median of a given key.\n     *\n     * @param  string|array|null  $key\n     * @return mixed\n     */\n    public function median($key = null)\n    {\n        return $this->collect()->median($key);\n    }\n\n    /**\n     * Get the mode of a given key.\n     *\n     * @param  string|array|null  $key\n     * @return array|null\n     */\n    public function mode($key = null)\n    {\n        return $this->collect()->mode($key);\n    }\n\n    /**\n     * Collapse the collection of items into a single array.\n     *\n     * @return static\n     */\n    public function collapse()\n    {\n        return new static(function () {\n            foreach ($this as $values) {\n                if (is_array($values) || $values instanceof Enumerable) {\n                    foreach ($values as $value) {\n                        yield $value;\n                    }\n                }\n            }\n        });\n    }\n\n    /**\n     * Determine if an item exists in the enumerable.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function contains($key, $operator = null, $value = null)\n    {\n        if (func_num_args() === 1 && $this->useAsCallable($key)) {\n            $placeholder = new stdClass;\n\n            return $this->first($key, $placeholder) !== $placeholder;\n        }\n\n        if (func_num_args() === 1) {\n            $needle = $key;\n\n            foreach ($this as $value) {\n                if ($value == $needle) {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        return $this->contains($this->operatorForWhere(...func_get_args()));\n    }\n\n    /**\n     * Determine if an item is not contained in the enumerable.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function doesntContain($key, $operator = null, $value = null)\n    {\n        return ! $this->contains(...func_get_args());\n    }\n\n    /**\n     * Cross join the given iterables, returning all possible permutations.\n     *\n     * @param  array  ...$arrays\n     * @return static\n     */\n    public function crossJoin(...$arrays)\n    {\n        return $this->passthru('crossJoin', func_get_args());\n    }\n\n    /**\n     * Count the number of items in the collection by a field or using a callback.\n     *\n     * @param  callable|string  $countBy\n     * @return static\n     */\n    public function countBy($countBy = null)\n    {\n        $countBy = is_null($countBy)\n            ? $this->identity()\n            : $this->valueRetriever($countBy);\n\n        return new static(function () use ($countBy) {\n            $counts = [];\n\n            foreach ($this as $key => $value) {\n                $group = $countBy($value, $key);\n\n                if (empty($counts[$group])) {\n                    $counts[$group] = 0;\n                }\n\n                $counts[$group]++;\n            }\n\n            yield from $counts;\n        });\n    }\n\n    /**\n     * Get the items that are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diff($items)\n    {\n        return $this->passthru('diff', func_get_args());\n    }\n\n    /**\n     * Get the items that are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffUsing($items, callable $callback)\n    {\n        return $this->passthru('diffUsing', func_get_args());\n    }\n\n    /**\n     * Get the items whose keys and values are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diffAssoc($items)\n    {\n        return $this->passthru('diffAssoc', func_get_args());\n    }\n\n    /**\n     * Get the items whose keys and values are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffAssocUsing($items, callable $callback)\n    {\n        return $this->passthru('diffAssocUsing', func_get_args());\n    }\n\n    /**\n     * Get the items whose keys are not present in the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function diffKeys($items)\n    {\n        return $this->passthru('diffKeys', func_get_args());\n    }\n\n    /**\n     * Get the items whose keys are not present in the given items, using the callback.\n     *\n     * @param  mixed  $items\n     * @param  callable  $callback\n     * @return static\n     */\n    public function diffKeysUsing($items, callable $callback)\n    {\n        return $this->passthru('diffKeysUsing', func_get_args());\n    }\n\n    /**\n     * Retrieve duplicate items.\n     *\n     * @param  callable|string|null  $callback\n     * @param  bool  $strict\n     * @return static\n     */\n    public function duplicates($callback = null, $strict = false)\n    {\n        return $this->passthru('duplicates', func_get_args());\n    }\n\n    /**\n     * Retrieve duplicate items using strict comparison.\n     *\n     * @param  callable|string|null  $callback\n     * @return static\n     */\n    public function duplicatesStrict($callback = null)\n    {\n        return $this->passthru('duplicatesStrict', func_get_args());\n    }\n\n    /**\n     * Get all items except for those with the specified keys.\n     *\n     * @param  mixed  $keys\n     * @return static\n     */\n    public function except($keys)\n    {\n        return $this->passthru('except', func_get_args());\n    }\n\n    /**\n     * Run a filter over each of the items.\n     *\n     * @param  callable|null  $callback\n     * @return static\n     */\n    public function filter(callable $callback = null)\n    {\n        if (is_null($callback)) {\n            $callback = function ($value) {\n                return (bool) $value;\n            };\n        }\n\n        return new static(function () use ($callback) {\n            foreach ($this as $key => $value) {\n                if ($callback($value, $key)) {\n                    yield $key => $value;\n                }\n            }\n        });\n    }\n\n    /**\n     * Get the first item from the enumerable passing the given truth test.\n     *\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function first(callable $callback = null, $default = null)\n    {\n        $iterator = $this->getIterator();\n\n        if (is_null($callback)) {\n            if (! $iterator->valid()) {\n                return value($default);\n            }\n\n            return $iterator->current();\n        }\n\n        foreach ($iterator as $key => $value) {\n            if ($callback($value, $key)) {\n                return $value;\n            }\n        }\n\n        return value($default);\n    }\n\n    /**\n     * Get a flattened list of the items in the collection.\n     *\n     * @param  int  $depth\n     * @return static\n     */\n    public function flatten($depth = INF)\n    {\n        $instance = new static(function () use ($depth) {\n            foreach ($this as $item) {\n                if (! is_array($item) && ! $item instanceof Enumerable) {\n                    yield $item;\n                } elseif ($depth === 1) {\n                    yield from $item;\n                } else {\n                    yield from (new static($item))->flatten($depth - 1);\n                }\n            }\n        });\n\n        return $instance->values();\n    }\n\n    /**\n     * Flip the items in the collection.\n     *\n     * @return static\n     */\n    public function flip()\n    {\n        return new static(function () {\n            foreach ($this as $key => $value) {\n                yield $value => $key;\n            }\n        });\n    }\n\n    /**\n     * Get an item by key.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function get($key, $default = null)\n    {\n        if (is_null($key)) {\n            return;\n        }\n\n        foreach ($this as $outerKey => $outerValue) {\n            if ($outerKey == $key) {\n                return $outerValue;\n            }\n        }\n\n        return value($default);\n    }\n\n    /**\n     * Group an associative array by a field or using a callback.\n     *\n     * @param  array|callable|string  $groupBy\n     * @param  bool  $preserveKeys\n     * @return static\n     */\n    public function groupBy($groupBy, $preserveKeys = false)\n    {\n        return $this->passthru('groupBy', func_get_args());\n    }\n\n    /**\n     * Key an associative array by a field or using a callback.\n     *\n     * @param  callable|string  $keyBy\n     * @return static\n     */\n    public function keyBy($keyBy)\n    {\n        return new static(function () use ($keyBy) {\n            $keyBy = $this->valueRetriever($keyBy);\n\n            foreach ($this as $key => $item) {\n                $resolvedKey = $keyBy($item, $key);\n\n                if (is_object($resolvedKey)) {\n                    $resolvedKey = (string) $resolvedKey;\n                }\n\n                yield $resolvedKey => $item;\n            }\n        });\n    }\n\n    /**\n     * Determine if an item exists in the collection by key.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    public function has($key)\n    {\n        $keys = array_flip(is_array($key) ? $key : func_get_args());\n        $count = count($keys);\n\n        foreach ($this as $key => $value) {\n            if (array_key_exists($key, $keys) && --$count == 0) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Determine if any of the keys exist in the collection.\n     *\n     * @param  mixed  $key\n     * @return bool\n     */\n    public function hasAny($key)\n    {\n        $keys = array_flip(is_array($key) ? $key : func_get_args());\n\n        foreach ($this as $key => $value) {\n            if (array_key_exists($key, $keys)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Concatenate values of a given key as a string.\n     *\n     * @param  string  $value\n     * @param  string|null  $glue\n     * @return string\n     */\n    public function implode($value, $glue = null)\n    {\n        return $this->collect()->implode(...func_get_args());\n    }\n\n    /**\n     * Intersect the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function intersect($items)\n    {\n        return $this->passthru('intersect', func_get_args());\n    }\n\n    /**\n     * Intersect the collection with the given items by key.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function intersectByKeys($items)\n    {\n        return $this->passthru('intersectByKeys', func_get_args());\n    }\n\n    /**\n     * Determine if the items are empty or not.\n     *\n     * @return bool\n     */\n    public function isEmpty()\n    {\n        return ! $this->getIterator()->valid();\n    }\n\n    /**\n     * Determine if the collection contains a single item.\n     *\n     * @return bool\n     */\n    public function containsOneItem()\n    {\n        return $this->take(2)->count() === 1;\n    }\n\n    /**\n     * Join all items from the collection using a string. The final items can use a separate glue string.\n     *\n     * @param  string  $glue\n     * @param  string  $finalGlue\n     * @return string\n     */\n    public function join($glue, $finalGlue = '')\n    {\n        return $this->collect()->join(...func_get_args());\n    }\n\n    /**\n     * Get the keys of the collection items.\n     *\n     * @return static\n     */\n    public function keys()\n    {\n        return new static(function () {\n            foreach ($this as $key => $value) {\n                yield $key;\n            }\n        });\n    }\n\n    /**\n     * Get the last item from the collection.\n     *\n     * @param  callable|null  $callback\n     * @param  mixed  $default\n     * @return mixed\n     */\n    public function last(callable $callback = null, $default = null)\n    {\n        $needle = $placeholder = new stdClass;\n\n        foreach ($this as $key => $value) {\n            if (is_null($callback) || $callback($value, $key)) {\n                $needle = $value;\n            }\n        }\n\n        return $needle === $placeholder ? value($default) : $needle;\n    }\n\n    /**\n     * Get the values of a given key.\n     *\n     * @param  string|array  $value\n     * @param  string|null  $key\n     * @return static\n     */\n    public function pluck($value, $key = null)\n    {\n        return new static(function () use ($value, $key) {\n            [$value, $key] = $this->explodePluckParameters($value, $key);\n\n            foreach ($this as $item) {\n                $itemValue = data_get($item, $value);\n\n                if (is_null($key)) {\n                    yield $itemValue;\n                } else {\n                    $itemKey = data_get($item, $key);\n\n                    if (is_object($itemKey) && method_exists($itemKey, '__toString')) {\n                        $itemKey = (string) $itemKey;\n                    }\n\n                    yield $itemKey => $itemValue;\n                }\n            }\n        });\n    }\n\n    /**\n     * Run a map over each of the items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function map(callable $callback)\n    {\n        return new static(function () use ($callback) {\n            foreach ($this as $key => $value) {\n                yield $key => $callback($value, $key);\n            }\n        });\n    }\n\n    /**\n     * Run a dictionary map over the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapToDictionary(callable $callback)\n    {\n        return $this->passthru('mapToDictionary', func_get_args());\n    }\n\n    /**\n     * Run an associative map over each of the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapWithKeys(callable $callback)\n    {\n        return new static(function () use ($callback) {\n            foreach ($this as $key => $value) {\n                yield from $callback($value, $key);\n            }\n        });\n    }\n\n    /**\n     * Merge the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function merge($items)\n    {\n        return $this->passthru('merge', func_get_args());\n    }\n\n    /**\n     * Recursively merge the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function mergeRecursive($items)\n    {\n        return $this->passthru('mergeRecursive', func_get_args());\n    }\n\n    /**\n     * Create a collection by using this collection for keys and another for its values.\n     *\n     * @param  mixed  $values\n     * @return static\n     */\n    public function combine($values)\n    {\n        return new static(function () use ($values) {\n            $values = $this->makeIterator($values);\n\n            $errorMessage = 'Both parameters should have an equal number of elements';\n\n            foreach ($this as $key) {\n                if (! $values->valid()) {\n                    trigger_error($errorMessage, E_USER_WARNING);\n\n                    break;\n                }\n\n                yield $key => $values->current();\n\n                $values->next();\n            }\n\n            if ($values->valid()) {\n                trigger_error($errorMessage, E_USER_WARNING);\n            }\n        });\n    }\n\n    /**\n     * Union the collection with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function union($items)\n    {\n        return $this->passthru('union', func_get_args());\n    }\n\n    /**\n     * Create a new collection consisting of every n-th element.\n     *\n     * @param  int  $step\n     * @param  int  $offset\n     * @return static\n     */\n    public function nth($step, $offset = 0)\n    {\n        return new static(function () use ($step, $offset) {\n            $position = 0;\n\n            foreach ($this as $item) {\n                if ($position % $step === $offset) {\n                    yield $item;\n                }\n\n                $position++;\n            }\n        });\n    }\n\n    /**\n     * Get the items with the specified keys.\n     *\n     * @param  mixed  $keys\n     * @return static\n     */\n    public function only($keys)\n    {\n        if ($keys instanceof Enumerable) {\n            $keys = $keys->all();\n        } elseif (! is_null($keys)) {\n            $keys = is_array($keys) ? $keys : func_get_args();\n        }\n\n        return new static(function () use ($keys) {\n            if (is_null($keys)) {\n                yield from $this;\n            } else {\n                $keys = array_flip($keys);\n\n                foreach ($this as $key => $value) {\n                    if (array_key_exists($key, $keys)) {\n                        yield $key => $value;\n\n                        unset($keys[$key]);\n\n                        if (empty($keys)) {\n                            break;\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n    /**\n     * Push all of the given items onto the collection.\n     *\n     * @param  iterable  $source\n     * @return static\n     */\n    public function concat($source)\n    {\n        return (new static(function () use ($source) {\n            yield from $this;\n            yield from $source;\n        }))->values();\n    }\n\n    /**\n     * Get one or a specified number of items randomly from the collection.\n     *\n     * @param  int|null  $number\n     * @return static|mixed\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public function random($number = null)\n    {\n        $result = $this->collect()->random(...func_get_args());\n\n        return is_null($number) ? $result : new static($result);\n    }\n\n    /**\n     * Replace the collection items with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function replace($items)\n    {\n        return new static(function () use ($items) {\n            $items = $this->getArrayableItems($items);\n\n            foreach ($this as $key => $value) {\n                if (array_key_exists($key, $items)) {\n                    yield $key => $items[$key];\n\n                    unset($items[$key]);\n                } else {\n                    yield $key => $value;\n                }\n            }\n\n            foreach ($items as $key => $value) {\n                yield $key => $value;\n            }\n        });\n    }\n\n    /**\n     * Recursively replace the collection items with the given items.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public function replaceRecursive($items)\n    {\n        return $this->passthru('replaceRecursive', func_get_args());\n    }\n\n    /**\n     * Reverse items order.\n     *\n     * @return static\n     */\n    public function reverse()\n    {\n        return $this->passthru('reverse', func_get_args());\n    }\n\n    /**\n     * Search the collection for a given value and return the corresponding key if successful.\n     *\n     * @param  mixed  $value\n     * @param  bool  $strict\n     * @return mixed\n     */\n    public function search($value, $strict = false)\n    {\n        $predicate = $this->useAsCallable($value)\n            ? $value\n            : function ($item) use ($value, $strict) {\n                return $strict ? $item === $value : $item == $value;\n            };\n\n        foreach ($this as $key => $item) {\n            if ($predicate($item, $key)) {\n                return $key;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Shuffle the items in the collection.\n     *\n     * @param  int|null  $seed\n     * @return static\n     */\n    public function shuffle($seed = null)\n    {\n        return $this->passthru('shuffle', func_get_args());\n    }\n\n    /**\n     * Create chunks representing a \"sliding window\" view of the items in the collection.\n     *\n     * @param  int  $size\n     * @param  int  $step\n     * @return static\n     */\n    public function sliding($size = 2, $step = 1)\n    {\n        return new static(function () use ($size, $step) {\n            $iterator = $this->getIterator();\n\n            $chunk = [];\n\n            while ($iterator->valid()) {\n                $chunk[$iterator->key()] = $iterator->current();\n\n                if (count($chunk) == $size) {\n                    yield tap(new static($chunk), function () use (&$chunk, $step) {\n                        $chunk = array_slice($chunk, $step, null, true);\n                    });\n\n                    // If the $step between chunks is bigger than each chunk's $size\n                    // we will skip the extra items (which should never be in any\n                    // chunk) before we continue to the next chunk in the loop.\n                    if ($step > $size) {\n                        $skip = $step - $size;\n\n                        for ($i = 0; $i < $skip && $iterator->valid(); $i++) {\n                            $iterator->next();\n                        }\n                    }\n                }\n\n                $iterator->next();\n            }\n        });\n    }\n\n    /**\n     * Skip the first {$count} items.\n     *\n     * @param  int  $count\n     * @return static\n     */\n    public function skip($count)\n    {\n        return new static(function () use ($count) {\n            $iterator = $this->getIterator();\n\n            while ($iterator->valid() && $count--) {\n                $iterator->next();\n            }\n\n            while ($iterator->valid()) {\n                yield $iterator->key() => $iterator->current();\n\n                $iterator->next();\n            }\n        });\n    }\n\n    /**\n     * Skip items in the collection until the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function skipUntil($value)\n    {\n        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);\n\n        return $this->skipWhile($this->negate($callback));\n    }\n\n    /**\n     * Skip items in the collection while the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function skipWhile($value)\n    {\n        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);\n\n        return new static(function () use ($callback) {\n            $iterator = $this->getIterator();\n\n            while ($iterator->valid() && $callback($iterator->current(), $iterator->key())) {\n                $iterator->next();\n            }\n\n            while ($iterator->valid()) {\n                yield $iterator->key() => $iterator->current();\n\n                $iterator->next();\n            }\n        });\n    }\n\n    /**\n     * Get a slice of items from the enumerable.\n     *\n     * @param  int  $offset\n     * @param  int|null  $length\n     * @return static\n     */\n    public function slice($offset, $length = null)\n    {\n        if ($offset < 0 || $length < 0) {\n            return $this->passthru('slice', func_get_args());\n        }\n\n        $instance = $this->skip($offset);\n\n        return is_null($length) ? $instance : $instance->take($length);\n    }\n\n    /**\n     * Split a collection into a certain number of groups.\n     *\n     * @param  int  $numberOfGroups\n     * @return static\n     */\n    public function split($numberOfGroups)\n    {\n        return $this->passthru('split', func_get_args());\n    }\n\n    /**\n     * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return mixed\n     *\n     * @throws \\Tightenco\\Collect\\Support\\ItemNotFoundException\n     * @throws \\Tightenco\\Collect\\Support\\MultipleItemsFoundException\n     */\n    public function sole($key = null, $operator = null, $value = null)\n    {\n        $filter = func_num_args() > 1\n            ? $this->operatorForWhere(...func_get_args())\n            : $key;\n\n        return $this\n            ->when($filter)\n            ->filter($filter)\n            ->take(2)\n            ->collect()\n            ->sole();\n    }\n\n    /**\n     * Get the first item in the collection but throw an exception if no matching items exist.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return mixed\n     *\n     * @throws \\Tightenco\\Collect\\Support\\ItemNotFoundException\n     */\n    public function firstOrFail($key = null, $operator = null, $value = null)\n    {\n        $filter = func_num_args() > 1\n            ? $this->operatorForWhere(...func_get_args())\n            : $key;\n\n        return $this\n            ->when($filter)\n            ->filter($filter)\n            ->take(1)\n            ->collect()\n            ->firstOrFail();\n    }\n\n    /**\n     * Chunk the collection into chunks of the given size.\n     *\n     * @param  int  $size\n     * @return static\n     */\n    public function chunk($size)\n    {\n        if ($size <= 0) {\n            return static::empty();\n        }\n\n        return new static(function () use ($size) {\n            $iterator = $this->getIterator();\n\n            while ($iterator->valid()) {\n                $chunk = [];\n\n                while (true) {\n                    $chunk[$iterator->key()] = $iterator->current();\n\n                    if (count($chunk) < $size) {\n                        $iterator->next();\n\n                        if (! $iterator->valid()) {\n                            break;\n                        }\n                    } else {\n                        break;\n                    }\n                }\n\n                yield new static($chunk);\n\n                $iterator->next();\n            }\n        });\n    }\n\n    /**\n     * Split a collection into a certain number of groups, and fill the first groups completely.\n     *\n     * @param  int  $numberOfGroups\n     * @return static\n     */\n    public function splitIn($numberOfGroups)\n    {\n        return $this->chunk(ceil($this->count() / $numberOfGroups));\n    }\n\n    /**\n     * Chunk the collection into chunks with a callback.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function chunkWhile(callable $callback)\n    {\n        return new static(function () use ($callback) {\n            $iterator = $this->getIterator();\n\n            $chunk = new Collection;\n\n            if ($iterator->valid()) {\n                $chunk[$iterator->key()] = $iterator->current();\n\n                $iterator->next();\n            }\n\n            while ($iterator->valid()) {\n                if (! $callback($iterator->current(), $iterator->key(), $chunk)) {\n                    yield new static($chunk);\n\n                    $chunk = new Collection;\n                }\n\n                $chunk[$iterator->key()] = $iterator->current();\n\n                $iterator->next();\n            }\n\n            if ($chunk->isNotEmpty()) {\n                yield new static($chunk);\n            }\n        });\n    }\n\n    /**\n     * Sort through each item with a callback.\n     *\n     * @param  callable|null|int  $callback\n     * @return static\n     */\n    public function sort($callback = null)\n    {\n        return $this->passthru('sort', func_get_args());\n    }\n\n    /**\n     * Sort items in descending order.\n     *\n     * @param  int  $options\n     * @return static\n     */\n    public function sortDesc($options = SORT_REGULAR)\n    {\n        return $this->passthru('sortDesc', func_get_args());\n    }\n\n    /**\n     * Sort the collection using the given callback.\n     *\n     * @param  callable|string  $callback\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return static\n     */\n    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)\n    {\n        return $this->passthru('sortBy', func_get_args());\n    }\n\n    /**\n     * Sort the collection in descending order using the given callback.\n     *\n     * @param  callable|string  $callback\n     * @param  int  $options\n     * @return static\n     */\n    public function sortByDesc($callback, $options = SORT_REGULAR)\n    {\n        return $this->passthru('sortByDesc', func_get_args());\n    }\n\n    /**\n     * Sort the collection keys.\n     *\n     * @param  int  $options\n     * @param  bool  $descending\n     * @return static\n     */\n    public function sortKeys($options = SORT_REGULAR, $descending = false)\n    {\n        return $this->passthru('sortKeys', func_get_args());\n    }\n\n    /**\n     * Sort the collection keys in descending order.\n     *\n     * @param  int  $options\n     * @return static\n     */\n    public function sortKeysDesc($options = SORT_REGULAR)\n    {\n        return $this->passthru('sortKeysDesc', func_get_args());\n    }\n\n    /**\n     * Take the first or last {$limit} items.\n     *\n     * @param  int  $limit\n     * @return static\n     */\n    public function take($limit)\n    {\n        if ($limit < 0) {\n            return $this->passthru('take', func_get_args());\n        }\n\n        return new static(function () use ($limit) {\n            $iterator = $this->getIterator();\n\n            while ($limit--) {\n                if (! $iterator->valid()) {\n                    break;\n                }\n\n                yield $iterator->key() => $iterator->current();\n\n                if ($limit) {\n                    $iterator->next();\n                }\n            }\n        });\n    }\n\n    /**\n     * Take items in the collection until the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function takeUntil($value)\n    {\n        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);\n\n        return new static(function () use ($callback) {\n            foreach ($this as $key => $item) {\n                if ($callback($item, $key)) {\n                    break;\n                }\n\n                yield $key => $item;\n            }\n        });\n    }\n\n    /**\n     * Take items in the collection until a given point in time.\n     *\n     * @param  \\DateTimeInterface  $timeout\n     * @return static\n     */\n    public function takeUntilTimeout(DateTimeInterface $timeout)\n    {\n        $timeout = $timeout->getTimestamp();\n\n        return $this->takeWhile(function () use ($timeout) {\n            return $this->now() < $timeout;\n        });\n    }\n\n    /**\n     * Take items in the collection while the given condition is met.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public function takeWhile($value)\n    {\n        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);\n\n        return $this->takeUntil(function ($item, $key) use ($callback) {\n            return ! $callback($item, $key);\n        });\n    }\n\n    /**\n     * Pass each item in the collection to the given callback, lazily.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function tapEach(callable $callback)\n    {\n        return new static(function () use ($callback) {\n            foreach ($this as $key => $value) {\n                $callback($value, $key);\n\n                yield $key => $value;\n            }\n        });\n    }\n\n    /**\n     * Convert a flatten \"dot\" notation array into an expanded array.\n     *\n     * @return static\n     */\n    public function undot()\n    {\n        return $this->passthru('undot', []);\n    }\n\n    /**\n     * Return only unique items from the collection array.\n     *\n     * @param  string|callable|null  $key\n     * @param  bool  $strict\n     * @return static\n     */\n    public function unique($key = null, $strict = false)\n    {\n        $callback = $this->valueRetriever($key);\n\n        return new static(function () use ($callback, $strict) {\n            $exists = [];\n\n            foreach ($this as $key => $item) {\n                if (! in_array($id = $callback($item, $key), $exists, $strict)) {\n                    yield $key => $item;\n\n                    $exists[] = $id;\n                }\n            }\n        });\n    }\n\n    /**\n     * Reset the keys on the underlying array.\n     *\n     * @return static\n     */\n    public function values()\n    {\n        return new static(function () {\n            foreach ($this as $item) {\n                yield $item;\n            }\n        });\n    }\n\n    /**\n     * Zip the collection together with one or more arrays.\n     *\n     * e.g. new LazyCollection([1, 2, 3])->zip([4, 5, 6]);\n     *      => [[1, 4], [2, 5], [3, 6]]\n     *\n     * @param  mixed  ...$items\n     * @return static\n     */\n    public function zip($items)\n    {\n        $iterables = func_get_args();\n\n        return new static(function () use ($iterables) {\n            $iterators = Collection::make($iterables)->map(function ($iterable) {\n                return $this->makeIterator($iterable);\n            })->prepend($this->getIterator());\n\n            while ($iterators->contains->valid()) {\n                yield new static($iterators->map->current());\n\n                $iterators->each->next();\n            }\n        });\n    }\n\n    /**\n     * Pad collection to the specified length with a value.\n     *\n     * @param  int  $size\n     * @param  mixed  $value\n     * @return static\n     */\n    public function pad($size, $value)\n    {\n        if ($size < 0) {\n            return $this->passthru('pad', func_get_args());\n        }\n\n        return new static(function () use ($size, $value) {\n            $yielded = 0;\n\n            foreach ($this as $index => $item) {\n                yield $index => $item;\n\n                $yielded++;\n            }\n\n            while ($yielded++ < $size) {\n                yield $value;\n            }\n        });\n    }\n\n    /**\n     * Get the values iterator.\n     *\n     * @return \\Traversable\n     */\n    #[\\ReturnTypeWillChange]\n    public function getIterator()\n    {\n        return $this->makeIterator($this->source);\n    }\n\n    /**\n     * Count the number of items in the collection.\n     *\n     * @return int\n     */\n    #[\\ReturnTypeWillChange]\n    public function count()\n    {\n        if (is_array($this->source)) {\n            return count($this->source);\n        }\n\n        return iterator_count($this->getIterator());\n    }\n\n    /**\n     * Make an iterator from the given source.\n     *\n     * @param  mixed  $source\n     * @return \\Traversable\n     */\n    protected function makeIterator($source)\n    {\n        if ($source instanceof IteratorAggregate) {\n            return $source->getIterator();\n        }\n\n        if (is_array($source)) {\n            return new ArrayIterator($source);\n        }\n\n        return $source();\n    }\n\n    /**\n     * Explode the \"value\" and \"key\" arguments passed to \"pluck\".\n     *\n     * @param  string|array  $value\n     * @param  string|array|null  $key\n     * @return array\n     */\n    protected function explodePluckParameters($value, $key)\n    {\n        $value = is_string($value) ? explode('.', $value) : $value;\n\n        $key = is_null($key) || is_array($key) ? $key : explode('.', $key);\n\n        return [$value, $key];\n    }\n\n    /**\n     * Pass this lazy collection through a method on the collection class.\n     *\n     * @param  string  $method\n     * @param  array  $params\n     * @return static\n     */\n    protected function passthru($method, array $params)\n    {\n        return new static(function () use ($method, $params) {\n            yield from $this->collect()->$method(...$params);\n        });\n    }\n\n    /**\n     * Get the current time.\n     *\n     * @return int\n     */\n    protected function now()\n    {\n        return time();\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/Traits/EnumeratesValues.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support\\Traits;\n\nuse CachingIterator;\nuse Closure;\nuse Exception;\nuse Tightenco\\Collect\\Contracts\\Support\\Arrayable;\nuse Tightenco\\Collect\\Contracts\\Support\\Jsonable;\nuse Tightenco\\Collect\\Support\\Arr;\nuse Tightenco\\Collect\\Support\\Collection;\nuse Tightenco\\Collect\\Support\\Enumerable;\nuse Tightenco\\Collect\\Support\\HigherOrderCollectionProxy;\nuse Tightenco\\Collect\\Support\\HigherOrderWhenProxy;\nuse JsonSerializable;\nuse Symfony\\Component\\VarDumper\\VarDumper;\nuse Traversable;\nuse UnexpectedValueException;\n\n/**\n * @property-read HigherOrderCollectionProxy $average\n * @property-read HigherOrderCollectionProxy $avg\n * @property-read HigherOrderCollectionProxy $contains\n * @property-read HigherOrderCollectionProxy $each\n * @property-read HigherOrderCollectionProxy $every\n * @property-read HigherOrderCollectionProxy $filter\n * @property-read HigherOrderCollectionProxy $first\n * @property-read HigherOrderCollectionProxy $flatMap\n * @property-read HigherOrderCollectionProxy $groupBy\n * @property-read HigherOrderCollectionProxy $keyBy\n * @property-read HigherOrderCollectionProxy $map\n * @property-read HigherOrderCollectionProxy $max\n * @property-read HigherOrderCollectionProxy $min\n * @property-read HigherOrderCollectionProxy $partition\n * @property-read HigherOrderCollectionProxy $reject\n * @property-read HigherOrderCollectionProxy $some\n * @property-read HigherOrderCollectionProxy $sortBy\n * @property-read HigherOrderCollectionProxy $sortByDesc\n * @property-read HigherOrderCollectionProxy $skipUntil\n * @property-read HigherOrderCollectionProxy $skipWhile\n * @property-read HigherOrderCollectionProxy $sum\n * @property-read HigherOrderCollectionProxy $takeUntil\n * @property-read HigherOrderCollectionProxy $takeWhile\n * @property-read HigherOrderCollectionProxy $unique\n * @property-read HigherOrderCollectionProxy $until\n */\ntrait EnumeratesValues\n{\n    /**\n     * Indicates that the object's string representation should be escaped when __toString is invoked.\n     *\n     * @var bool\n     */\n    protected $escapeWhenCastingToString = false;\n\n    /**\n     * The methods that can be proxied.\n     *\n     * @var string[]\n     */\n    protected static $proxies = [\n        'average',\n        'avg',\n        'contains',\n        'each',\n        'every',\n        'filter',\n        'first',\n        'flatMap',\n        'groupBy',\n        'keyBy',\n        'map',\n        'max',\n        'min',\n        'partition',\n        'reject',\n        'skipUntil',\n        'skipWhile',\n        'some',\n        'sortBy',\n        'sortByDesc',\n        'sum',\n        'takeUntil',\n        'takeWhile',\n        'unique',\n        'until',\n    ];\n\n    /**\n     * Create a new collection instance if the value isn't one already.\n     *\n     * @param  mixed  $items\n     * @return static\n     */\n    public static function make($items = [])\n    {\n        return new static($items);\n    }\n\n    /**\n     * Wrap the given value in a collection if applicable.\n     *\n     * @param  mixed  $value\n     * @return static\n     */\n    public static function wrap($value)\n    {\n        return $value instanceof Enumerable\n            ? new static($value)\n            : new static(Arr::wrap($value));\n    }\n\n    /**\n     * Get the underlying items from the given collection if applicable.\n     *\n     * @param  array|static  $value\n     * @return array\n     */\n    public static function unwrap($value)\n    {\n        return $value instanceof Enumerable ? $value->all() : $value;\n    }\n\n    /**\n     * Create a new instance with no items.\n     *\n     * @return static\n     */\n    public static function empty()\n    {\n        return new static([]);\n    }\n\n    /**\n     * Create a new collection by invoking the callback a given amount of times.\n     *\n     * @param  int  $number\n     * @param  callable|null  $callback\n     * @return static\n     */\n    public static function times($number, callable $callback = null)\n    {\n        if ($number < 1) {\n            return new static;\n        }\n\n        return static::range(1, $number)\n            ->when($callback)\n            ->map($callback);\n    }\n\n    /**\n     * Alias for the \"avg\" method.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function average($callback = null)\n    {\n        return $this->avg($callback);\n    }\n\n    /**\n     * Alias for the \"contains\" method.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function some($key, $operator = null, $value = null)\n    {\n        return $this->contains(...func_get_args());\n    }\n\n    /**\n     * Determine if an item exists, using strict comparison.\n     *\n     * @param  mixed  $key\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function containsStrict($key, $value = null)\n    {\n        if (func_num_args() === 2) {\n            return $this->contains(function ($item) use ($key, $value) {\n                return data_get($item, $key) === $value;\n            });\n        }\n\n        if ($this->useAsCallable($key)) {\n            return ! is_null($this->first($key));\n        }\n\n        foreach ($this as $item) {\n            if ($item === $key) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Dump the items and end the script.\n     *\n     * @param  mixed  ...$args\n     * @return void\n     */\n    public function dd(...$args)\n    {\n        $this->dump(...$args);\n\n        exit(1);\n    }\n\n    /**\n     * Dump the items.\n     *\n     * @return $this\n     */\n    public function dump()\n    {\n        (new Collection(func_get_args()))\n            ->push($this->all())\n            ->each(function ($item) {\n                VarDumper::dump($item);\n            });\n\n        return $this;\n    }\n\n    /**\n     * Execute a callback over each item.\n     *\n     * @param  callable  $callback\n     * @return $this\n     */\n    public function each(callable $callback)\n    {\n        foreach ($this as $key => $item) {\n            if ($callback($item, $key) === false) {\n                break;\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Execute a callback over each nested chunk of items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function eachSpread(callable $callback)\n    {\n        return $this->each(function ($chunk, $key) use ($callback) {\n            $chunk[] = $key;\n\n            return $callback(...$chunk);\n        });\n    }\n\n    /**\n     * Determine if all items pass the given truth test.\n     *\n     * @param  string|callable  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function every($key, $operator = null, $value = null)\n    {\n        if (func_num_args() === 1) {\n            $callback = $this->valueRetriever($key);\n\n            foreach ($this as $k => $v) {\n                if (! $callback($v, $k)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        return $this->every($this->operatorForWhere(...func_get_args()));\n    }\n\n    /**\n     * Get the first item by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return mixed\n     */\n    public function firstWhere($key, $operator = null, $value = null)\n    {\n        return $this->first($this->operatorForWhere(...func_get_args()));\n    }\n\n    /**\n     * Determine if the collection is not empty.\n     *\n     * @return bool\n     */\n    public function isNotEmpty()\n    {\n        return ! $this->isEmpty();\n    }\n\n    /**\n     * Run a map over each nested chunk of items.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapSpread(callable $callback)\n    {\n        return $this->map(function ($chunk, $key) use ($callback) {\n            $chunk[] = $key;\n\n            return $callback(...$chunk);\n        });\n    }\n\n    /**\n     * Run a grouping map over the items.\n     *\n     * The callback should return an associative array with a single key/value pair.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function mapToGroups(callable $callback)\n    {\n        $groups = $this->mapToDictionary($callback);\n\n        return $groups->map([$this, 'make']);\n    }\n\n    /**\n     * Map a collection and flatten the result by a single level.\n     *\n     * @param  callable  $callback\n     * @return static\n     */\n    public function flatMap(callable $callback)\n    {\n        return $this->map($callback)->collapse();\n    }\n\n    /**\n     * Map the values into a new class.\n     *\n     * @param  string  $class\n     * @return static\n     */\n    public function mapInto($class)\n    {\n        return $this->map(function ($value, $key) use ($class) {\n            return new $class($value, $key);\n        });\n    }\n\n    /**\n     * Get the min value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function min($callback = null)\n    {\n        $callback = $this->valueRetriever($callback);\n\n        return $this->map(function ($value) use ($callback) {\n            return $callback($value);\n        })->filter(function ($value) {\n            return ! is_null($value);\n        })->reduce(function ($result, $value) {\n            return is_null($result) || $value < $result ? $value : $result;\n        });\n    }\n\n    /**\n     * Get the max value of a given key.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function max($callback = null)\n    {\n        $callback = $this->valueRetriever($callback);\n\n        return $this->filter(function ($value) {\n            return ! is_null($value);\n        })->reduce(function ($result, $item) use ($callback) {\n            $value = $callback($item);\n\n            return is_null($result) || $value > $result ? $value : $result;\n        });\n    }\n\n    /**\n     * \"Paginate\" the collection by slicing it into a smaller collection.\n     *\n     * @param  int  $page\n     * @param  int  $perPage\n     * @return static\n     */\n    public function forPage($page, $perPage)\n    {\n        $offset = max(0, ($page - 1) * $perPage);\n\n        return $this->slice($offset, $perPage);\n    }\n\n    /**\n     * Partition the collection into two arrays using the given callback or key.\n     *\n     * @param  callable|string  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return static\n     */\n    public function partition($key, $operator = null, $value = null)\n    {\n        $passed = [];\n        $failed = [];\n\n        $callback = func_num_args() === 1\n                ? $this->valueRetriever($key)\n                : $this->operatorForWhere(...func_get_args());\n\n        foreach ($this as $key => $item) {\n            if ($callback($item, $key)) {\n                $passed[$key] = $item;\n            } else {\n                $failed[$key] = $item;\n            }\n        }\n\n        return new static([new static($passed), new static($failed)]);\n    }\n\n    /**\n     * Get the sum of the given values.\n     *\n     * @param  callable|string|null  $callback\n     * @return mixed\n     */\n    public function sum($callback = null)\n    {\n        $callback = is_null($callback)\n            ? $this->identity()\n            : $this->valueRetriever($callback);\n\n        return $this->reduce(function ($result, $item) use ($callback) {\n            return $result + $callback($item);\n        }, 0);\n    }\n\n    /**\n     * Apply the callback if the value is truthy.\n     *\n     * @param  bool|mixed  $value\n     * @param  callable|null  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function when($value, callable $callback = null, callable $default = null)\n    {\n        if (! $callback) {\n            return new HigherOrderWhenProxy($this, $value);\n        }\n\n        if ($value) {\n            return $callback($this, $value);\n        } elseif ($default) {\n            return $default($this, $value);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Apply the callback if the collection is empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function whenEmpty(callable $callback, callable $default = null)\n    {\n        return $this->when($this->isEmpty(), $callback, $default);\n    }\n\n    /**\n     * Apply the callback if the collection is not empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function whenNotEmpty(callable $callback, callable $default = null)\n    {\n        return $this->when($this->isNotEmpty(), $callback, $default);\n    }\n\n    /**\n     * Apply the callback if the value is falsy.\n     *\n     * @param  bool  $value\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function unless($value, callable $callback, callable $default = null)\n    {\n        return $this->when(! $value, $callback, $default);\n    }\n\n    /**\n     * Apply the callback unless the collection is empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function unlessEmpty(callable $callback, callable $default = null)\n    {\n        return $this->whenNotEmpty($callback, $default);\n    }\n\n    /**\n     * Apply the callback unless the collection is not empty.\n     *\n     * @param  callable  $callback\n     * @param  callable|null  $default\n     * @return static|mixed\n     */\n    public function unlessNotEmpty(callable $callback, callable $default = null)\n    {\n        return $this->whenEmpty($callback, $default);\n    }\n\n    /**\n     * Filter items by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $operator\n     * @param  mixed  $value\n     * @return static\n     */\n    public function where($key, $operator = null, $value = null)\n    {\n        return $this->filter($this->operatorForWhere(...func_get_args()));\n    }\n\n    /**\n     * Filter items where the value for the given key is null.\n     *\n     * @param  string|null  $key\n     * @return static\n     */\n    public function whereNull($key = null)\n    {\n        return $this->whereStrict($key, null);\n    }\n\n    /**\n     * Filter items where the value for the given key is not null.\n     *\n     * @param  string|null  $key\n     * @return static\n     */\n    public function whereNotNull($key = null)\n    {\n        return $this->where($key, '!==', null);\n    }\n\n    /**\n     * Filter items by the given key value pair using strict comparison.\n     *\n     * @param  string  $key\n     * @param  mixed  $value\n     * @return static\n     */\n    public function whereStrict($key, $value)\n    {\n        return $this->where($key, '===', $value);\n    }\n\n    /**\n     * Filter items by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @param  bool  $strict\n     * @return static\n     */\n    public function whereIn($key, $values, $strict = false)\n    {\n        $values = $this->getArrayableItems($values);\n\n        return $this->filter(function ($item) use ($key, $values, $strict) {\n            return in_array(data_get($item, $key), $values, $strict);\n        });\n    }\n\n    /**\n     * Filter items by the given key value pair using strict comparison.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @return static\n     */\n    public function whereInStrict($key, $values)\n    {\n        return $this->whereIn($key, $values, true);\n    }\n\n    /**\n     * Filter items such that the value of the given key is between the given values.\n     *\n     * @param  string  $key\n     * @param  array  $values\n     * @return static\n     */\n    public function whereBetween($key, $values)\n    {\n        return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));\n    }\n\n    /**\n     * Filter items such that the value of the given key is not between the given values.\n     *\n     * @param  string  $key\n     * @param  array  $values\n     * @return static\n     */\n    public function whereNotBetween($key, $values)\n    {\n        return $this->filter(function ($item) use ($key, $values) {\n            return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);\n        });\n    }\n\n    /**\n     * Filter items by the given key value pair.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @param  bool  $strict\n     * @return static\n     */\n    public function whereNotIn($key, $values, $strict = false)\n    {\n        $values = $this->getArrayableItems($values);\n\n        return $this->reject(function ($item) use ($key, $values, $strict) {\n            return in_array(data_get($item, $key), $values, $strict);\n        });\n    }\n\n    /**\n     * Filter items by the given key value pair using strict comparison.\n     *\n     * @param  string  $key\n     * @param  mixed  $values\n     * @return static\n     */\n    public function whereNotInStrict($key, $values)\n    {\n        return $this->whereNotIn($key, $values, true);\n    }\n\n    /**\n     * Filter the items, removing any items that don't match the given type(s).\n     *\n     * @param  string|string[]  $type\n     * @return static\n     */\n    public function whereInstanceOf($type)\n    {\n        return $this->filter(function ($value) use ($type) {\n            if (is_array($type)) {\n                foreach ($type as $classType) {\n                    if ($value instanceof $classType) {\n                        return true;\n                    }\n                }\n\n                return false;\n            }\n\n            return $value instanceof $type;\n        });\n    }\n\n    /**\n     * Pass the collection to the given callback and return the result.\n     *\n     * @param  callable  $callback\n     * @return mixed\n     */\n    public function pipe(callable $callback)\n    {\n        return $callback($this);\n    }\n\n    /**\n     * Pass the collection into a new class.\n     *\n     * @param  string  $class\n     * @return mixed\n     */\n    public function pipeInto($class)\n    {\n        return new $class($this);\n    }\n\n    /**\n     * Pass the collection to the given callback and then return it.\n     *\n     * @param  callable  $callback\n     * @return $this\n     */\n    public function tap(callable $callback)\n    {\n        $callback(clone $this);\n\n        return $this;\n    }\n\n    /**\n     * Reduce the collection to a single value.\n     *\n     * @param  callable  $callback\n     * @param  mixed  $initial\n     * @return mixed\n     */\n    public function reduce(callable $callback, $initial = null)\n    {\n        $result = $initial;\n\n        foreach ($this as $key => $value) {\n            $result = $callback($result, $value, $key);\n        }\n\n        return $result;\n    }\n\n    /**\n     * Reduce the collection to multiple aggregate values.\n     *\n     * @param  callable  $callback\n     * @param  mixed  ...$initial\n     * @return array\n     *\n     * @deprecated Use \"reduceSpread\" instead\n     *\n     * @throws \\UnexpectedValueException\n     */\n    public function reduceMany(callable $callback, ...$initial)\n    {\n        return $this->reduceSpread($callback, ...$initial);\n    }\n\n    /**\n     * Reduce the collection to multiple aggregate values.\n     *\n     * @param  callable  $callback\n     * @param  mixed  ...$initial\n     * @return array\n     *\n     * @throws \\UnexpectedValueException\n     */\n    public function reduceSpread(callable $callback, ...$initial)\n    {\n        $result = $initial;\n\n        foreach ($this as $key => $value) {\n            $result = call_user_func_array($callback, array_merge($result, [$value, $key]));\n\n            if (! is_array($result)) {\n                throw new UnexpectedValueException(sprintf(\n                    \"%s::reduceMany expects reducer to return an array, but got a '%s' instead.\",\n                    class_basename(static::class), gettype($result)\n                ));\n            }\n        }\n\n        return $result;\n    }\n\n    /**\n     * Reduce an associative collection to a single value.\n     *\n     * @param  callable  $callback\n     * @param  mixed  $initial\n     * @return mixed\n     */\n    public function reduceWithKeys(callable $callback, $initial = null)\n    {\n        return $this->reduce($callback, $initial);\n    }\n\n    /**\n     * Create a collection of all elements that do not pass a given truth test.\n     *\n     * @param  callable|mixed  $callback\n     * @return static\n     */\n    public function reject($callback = true)\n    {\n        $useAsCallable = $this->useAsCallable($callback);\n\n        return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {\n            return $useAsCallable\n                ? ! $callback($value, $key)\n                : $value != $callback;\n        });\n    }\n\n    /**\n     * Return only unique items from the collection array using strict comparison.\n     *\n     * @param  string|callable|null  $key\n     * @return static\n     */\n    public function uniqueStrict($key = null)\n    {\n        return $this->unique($key, true);\n    }\n\n    /**\n     * Collect the values into a collection.\n     *\n     * @return \\Tightenco\\Collect\\Support\\Collection\n     */\n    public function collect()\n    {\n        return new Collection($this->all());\n    }\n\n    /**\n     * Get the collection of items as a plain array.\n     *\n     * @return array\n     */\n    public function toArray()\n    {\n        return $this->map(function ($value) {\n            return $value instanceof Arrayable ? $value->toArray() : $value;\n        })->all();\n    }\n\n    /**\n     * Convert the object into something JSON serializable.\n     *\n     * @return array\n     */\n    #[\\ReturnTypeWillChange]\n    public function jsonSerialize()\n    {\n        return array_map(function ($value) {\n            if ($value instanceof JsonSerializable) {\n                return $value->jsonSerialize();\n            } elseif ($value instanceof Jsonable) {\n                return json_decode($value->toJson(), true);\n            } elseif ($value instanceof Arrayable) {\n                return $value->toArray();\n            }\n\n            return $value;\n        }, $this->all());\n    }\n\n    /**\n     * Get the collection of items as JSON.\n     *\n     * @param  int  $options\n     * @return string\n     */\n    public function toJson($options = 0)\n    {\n        return json_encode($this->jsonSerialize(), $options);\n    }\n\n    /**\n     * Get a CachingIterator instance.\n     *\n     * @param  int  $flags\n     * @return \\CachingIterator\n     */\n    public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)\n    {\n        return new CachingIterator($this->getIterator(), $flags);\n    }\n\n    /**\n     * Convert the collection to its string representation.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->escapeWhenCastingToString\n                    ? e($this->toJson())\n                    : $this->toJson();\n    }\n\n    /**\n     * Indicate that the model's string representation should be escaped when __toString is invoked.\n     *\n     * @param  bool  $escape\n     * @return $this\n     */\n    public function escapeWhenCastingToString($escape = true)\n    {\n        $this->escapeWhenCastingToString = $escape;\n\n        return $this;\n    }\n\n    /**\n     * Add a method to the list of proxied methods.\n     *\n     * @param  string  $method\n     * @return void\n     */\n    public static function proxy($method)\n    {\n        static::$proxies[] = $method;\n    }\n\n    /**\n     * Dynamically access collection proxies.\n     *\n     * @param  string  $key\n     * @return mixed\n     *\n     * @throws \\Exception\n     */\n    public function __get($key)\n    {\n        if (! in_array($key, static::$proxies)) {\n            throw new Exception(\"Property [{$key}] does not exist on this collection instance.\");\n        }\n\n        return new HigherOrderCollectionProxy($this, $key);\n    }\n\n    /**\n     * Results array of items from Collection or Arrayable.\n     *\n     * @param  mixed  $items\n     * @return array\n     */\n    protected function getArrayableItems($items)\n    {\n        if (is_array($items)) {\n            return $items;\n        } elseif ($items instanceof Enumerable) {\n            return $items->all();\n        } elseif ($items instanceof Arrayable) {\n            return $items->toArray();\n        } elseif ($items instanceof Jsonable) {\n            return json_decode($items->toJson(), true);\n        } elseif ($items instanceof JsonSerializable) {\n            return (array) $items->jsonSerialize();\n        } elseif ($items instanceof Traversable) {\n            return iterator_to_array($items);\n        }\n\n        return (array) $items;\n    }\n\n    /**\n     * Get an operator checker callback.\n     *\n     * @param  string  $key\n     * @param  string|null  $operator\n     * @param  mixed  $value\n     * @return \\Closure\n     */\n    protected function operatorForWhere($key, $operator = null, $value = null)\n    {\n        if (func_num_args() === 1) {\n            $value = true;\n\n            $operator = '=';\n        }\n\n        if (func_num_args() === 2) {\n            $value = $operator;\n\n            $operator = '=';\n        }\n\n        return function ($item) use ($key, $operator, $value) {\n            $retrieved = data_get($item, $key);\n\n            $strings = array_filter([$retrieved, $value], function ($value) {\n                return is_string($value) || (is_object($value) && method_exists($value, '__toString'));\n            });\n\n            if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {\n                return in_array($operator, ['!=', '<>', '!==']);\n            }\n\n            switch ($operator) {\n                default:\n                case '=':\n                case '==':  return $retrieved == $value;\n                case '!=':\n                case '<>':  return $retrieved != $value;\n                case '<':   return $retrieved < $value;\n                case '>':   return $retrieved > $value;\n                case '<=':  return $retrieved <= $value;\n                case '>=':  return $retrieved >= $value;\n                case '===': return $retrieved === $value;\n                case '!==': return $retrieved !== $value;\n            }\n        };\n    }\n\n    /**\n     * Determine if the given value is callable, but not a string.\n     *\n     * @param  mixed  $value\n     * @return bool\n     */\n    protected function useAsCallable($value)\n    {\n        return ! is_string($value) && is_callable($value);\n    }\n\n    /**\n     * Get a value retrieving callback.\n     *\n     * @param  callable|string|null  $value\n     * @return callable\n     */\n    protected function valueRetriever($value)\n    {\n        if ($this->useAsCallable($value)) {\n            return $value;\n        }\n\n        return function ($item) use ($value) {\n            return data_get($item, $value);\n        };\n    }\n\n    /**\n     * Make a function to check an item's equality.\n     *\n     * @param  mixed  $value\n     * @return \\Closure\n     */\n    protected function equality($value)\n    {\n        return function ($item) use ($value) {\n            return $item === $value;\n        };\n    }\n\n    /**\n     * Make a function using another function, by negating its result.\n     *\n     * @param  \\Closure  $callback\n     * @return \\Closure\n     */\n    protected function negate(Closure $callback)\n    {\n        return function (...$params) use ($callback) {\n            return ! $callback(...$params);\n        };\n    }\n\n    /**\n     * Make a function that returns what's passed to it.\n     *\n     * @return \\Closure\n     */\n    protected function identity()\n    {\n        return function ($value) {\n            return $value;\n        };\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/Traits/Macroable.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support\\Traits;\n\nuse BadMethodCallException;\nuse Closure;\nuse ReflectionClass;\nuse ReflectionMethod;\n\ntrait Macroable\n{\n    /**\n     * The registered string macros.\n     *\n     * @var array\n     */\n    protected static $macros = [];\n\n    /**\n     * Register a custom macro.\n     *\n     * @param  string  $name\n     * @param  object|callable  $macro\n     * @return void\n     */\n    public static function macro($name, $macro)\n    {\n        static::$macros[$name] = $macro;\n    }\n\n    /**\n     * Mix another object into the class.\n     *\n     * @param  object  $mixin\n     * @param  bool  $replace\n     * @return void\n     *\n     * @throws \\ReflectionException\n     */\n    public static function mixin($mixin, $replace = true)\n    {\n        $methods = (new ReflectionClass($mixin))->getMethods(\n            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED\n        );\n\n        foreach ($methods as $method) {\n            if ($replace || ! static::hasMacro($method->name)) {\n                $method->setAccessible(true);\n                static::macro($method->name, $method->invoke($mixin));\n            }\n        }\n    }\n\n    /**\n     * Checks if macro is registered.\n     *\n     * @param  string  $name\n     * @return bool\n     */\n    public static function hasMacro($name)\n    {\n        return isset(static::$macros[$name]);\n    }\n\n    /**\n     * Flush the existing macros.\n     *\n     * @return void\n     */\n    public static function flushMacros()\n    {\n        static::$macros = [];\n    }\n\n    /**\n     * Dynamically handle calls to the class.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     *\n     * @throws \\BadMethodCallException\n     */\n    public static function __callStatic($method, $parameters)\n    {\n        if (! static::hasMacro($method)) {\n            throw new BadMethodCallException(sprintf(\n                'Method %s::%s does not exist.', static::class, $method\n            ));\n        }\n\n        $macro = static::$macros[$method];\n\n        if ($macro instanceof Closure) {\n            $macro = $macro->bindTo(null, static::class);\n        }\n\n        return $macro(...$parameters);\n    }\n\n    /**\n     * Dynamically handle calls to the class.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     *\n     * @throws \\BadMethodCallException\n     */\n    public function __call($method, $parameters)\n    {\n        if (! static::hasMacro($method)) {\n            throw new BadMethodCallException(sprintf(\n                'Method %s::%s does not exist.', static::class, $method\n            ));\n        }\n\n        $macro = static::$macros[$method];\n\n        if ($macro instanceof Closure) {\n            $macro = $macro->bindTo($this, static::class);\n        }\n\n        return $macro(...$parameters);\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/Traits/Tappable.php",
    "content": "<?php\n\nnamespace Tightenco\\Collect\\Support\\Traits;\n\ntrait Tappable\n{\n    /**\n     * Call the given Closure with this instance then return the instance.\n     *\n     * @param  callable|null  $callback\n     * @return $this|\\Tightenco\\Collect\\Support\\HigherOrderTapProxy\n     */\n    public function tap($callback = null)\n    {\n        return tap($this, $callback);\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/alias.php",
    "content": "<?php\n\n$aliases = [\n    Tightenco\\Collect\\Contracts\\Support\\Arrayable::class => Illuminate\\Contracts\\Support\\Arrayable::class,\n    Tightenco\\Collect\\Contracts\\Support\\Jsonable::class => Illuminate\\Contracts\\Support\\Jsonable::class,\n    Tightenco\\Collect\\Contracts\\Support\\Htmlable::class => Illuminate\\Contracts\\Support\\Htmlable::class,\n    Tightenco\\Collect\\Contracts\\Support\\CanBeEscapedWhenCastToString::class => Illuminate\\Contracts\\Support\\CanBeEscapedWhenCastToString::class,\n    Tightenco\\Collect\\Support\\Arr::class => Illuminate\\Support\\Arr::class,\n    Tightenco\\Collect\\Support\\Collection::class => Illuminate\\Support\\Collection::class,\n    Tightenco\\Collect\\Support\\Enumerable::class => Illuminate\\Support\\Enumerable::class,\n    Tightenco\\Collect\\Support\\HigherOrderCollectionProxy::class => Illuminate\\Support\\HigherOrderCollectionProxy::class,\n    Tightenco\\Collect\\Support\\HigherOrderWhenProxy::class => Illuminate\\Support\\HigherOrderWhenProxy::class,\n    Tightenco\\Collect\\Support\\LazyCollection::class => Illuminate\\Support\\LazyCollection::class,\n    Tightenco\\Collect\\Support\\Traits\\EnumeratesValues::class => Illuminate\\Support\\Traits\\EnumeratesValues::class,\n];\n\n# echo \"\\n\\n-- Aliasing....\\n---------------------------------------------\\n\\n\";\n\nforeach ($aliases as $tighten => $illuminate) {\n    if (! class_exists($illuminate) && ! interface_exists($illuminate) && ! trait_exists($illuminate)) {\n        # echo \"Aliasing {$tighten} to {$illuminate}.\\n\";\n        class_alias($tighten, $illuminate);\n    }\n}\n"
  },
  {
    "path": "vendor/tightenco/collect/src/Collect/Support/helpers.php",
    "content": "<?php\n\nuse Tightenco\\Collect\\Support\\Arr;\nuse Tightenco\\Collect\\Support\\Collection;\nuse Tightenco\\Collect\\Support\\HigherOrderTapProxy;\nuse Symfony\\Component\\VarDumper\\VarDumper;\n\nif (! class_exists(Illuminate\\Support\\Collection::class)) {\n    if (! function_exists('array_wrap')) {\n        /**\n         * If the given value is not an array, wrap it in one.\n         *\n         * @param  mixed  $value\n         * @return array\n         */\n        function array_wrap($value)\n        {\n            return ! is_array($value) ? [$value] : $value;\n        }\n    }\n\n    if (! function_exists('collect')) {\n        /**\n         * Create a collection from the given value.\n         *\n         * @param  mixed  $value\n         * @return \\Tightenco\\Collect\\Support\\Collection\n         */\n        function collect($value = null)\n        {\n            return new Collection($value);\n        }\n    }\n\n    if (! function_exists('value')) {\n        /**\n         * Return the default value of the given value.\n         *\n         * @param  mixed  $value\n         * @return mixed\n         */\n        function value($value)\n        {\n            return $value instanceof Closure ? $value() : $value;\n        }\n    }\n\n    if (! function_exists('data_get')) {\n        /**\n         * Get an item from an array or object using \"dot\" notation.\n         *\n         * @param  mixed   $target\n         * @param  string|array  $key\n         * @param  mixed   $default\n         * @return mixed\n         */\n        function data_get($target, $key, $default = null)\n        {\n            if (is_null($key)) {\n                return $target;\n            }\n\n            $key = is_array($key) ? $key : explode('.', $key);\n\n            while (($segment = array_shift($key)) !== null) {\n                if ($segment === '*') {\n                    if ($target instanceof Collection) {\n                        $target = $target->all();\n                    } elseif (! is_array($target)) {\n                        return value($default);\n                    }\n\n                    $result = Arr::pluck($target, $key);\n\n                    return in_array('*', $key) ? Arr::collapse($result) : $result;\n                }\n\n                if (Arr::accessible($target) && Arr::exists($target, $segment)) {\n                    $target = $target[$segment];\n                } elseif (is_object($target) && isset($target->{$segment})) {\n                    $target = $target->{$segment};\n                } else {\n                    return value($default);\n                }\n            }\n\n            return $target;\n        }\n    }\n\n    if (! function_exists('tap')) {\n        /**\n         * Call the given Closure with the given value then return the value.\n         *\n         * @param  mixed  $value\n         * @param  callable|null  $callback\n         * @return mixed\n         */\n        function tap($value, $callback = null)\n        {\n            if (is_null($callback)) {\n                return new HigherOrderTapProxy($value);\n            }\n\n            $callback($value);\n\n            return $value;\n        }\n    }\n\n    if (! function_exists('with')) {\n        /**\n         * Return the given object. Useful for chaining.\n         *\n         * @param  mixed  $object\n         * @return mixed\n         */\n        function with($object)\n        {\n            return $object;\n        }\n    }\n\n    if (! function_exists('dd')) {\n        /**\n         * Dump the passed variables and end the script.\n         *\n         * @param  mixed\n         * @return void\n         */\n        function dd(...$args)\n        {\n            foreach ($args as $x) {\n               VarDumper::dump($x);\n            }\n            die(1);\n        }\n    }\n\n    if (! function_exists('class_basename')) {\n        /**\n         * Get the class \"basename\" of the given object / class.\n         *\n         * @param  string|object  $class\n         * @return string\n         */\n        function class_basename($class)\n        {\n            $class = is_object($class) ? get_class($class) : $class;\n\n            return basename(str_replace('\\\\', '/', $class));\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/.travis.yml",
    "content": "language: php\n\nphp:\n  - 5.3\n  - 5.4\n  - 5.5\n  - 5.6\n  - 7.0\n  - hhvm\n\nmatrix:\n  allow_failures:\n   - php: 7.0\n\nbefore_script:\n  - composer install --dev --prefer-source\n\nscript:\n  - php vendor/bin/phpunit\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/README.md",
    "content": "# php-semver -- The semantic versioner for npm ported to PHP\n\nPorted from [node-semver 1.1.2](https://github.com/isaacs/node-semver/tree/v1.1.2) to PHP\n\n[![Build Status](https://secure.travis-ci.org/vierbergenlars/php-semver.png?branch=master)](http://travis-ci.org/vierbergenlars/php-semver)\n[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/vierbergenlars/php-semver/badges/quality-score.png?s=89ff49019cde97e70228ae14d2dc08b727e72157)](https://scrutinizer-ci.com/g/vierbergenlars/php-semver/)\n[![Latest Stable Version](https://poser.pugx.org/vierbergenlars/php-semver/v/stable.png)](https://packagist.org/packages/vierbergenlars/php-semver)\n[![Total Downloads](https://poser.pugx.org/vierbergenlars/php-semver/downloads.png)](https://packagist.org/packages/vierbergenlars/php-semver)\n\n## Usage\n\n```php\n<?php\n\nuse vierbergenlars\\SemVer\\version;\nuse vierbergenlars\\SemVer\\expression;\nuse vierbergenlars\\SemVer\\SemVerException;\n\n// Check if a version is valid\n$semver = new version('1.2.3');\n$semver = new version('a.b.c'); //SemVerException thrown\n\n//Get a clean version string\n$semver = new version('=v1.2.3');\n$semver->getVersion(); //'1.2.3'\n\n//Check if a version satisfies a range\n$semver = new version('1.2.3');\n$semver->satisfies(new expression('1.x || >=2.5.0 || 5.0.0 - 7.2.3')); //true\n# OR\n$range = new expression('1.x || >=2.5.0 || 5.0.0 - 7.2.3');\n$range->satisfiedBy(new version('1.2.3')); //true\n\n//Compare two versions\nversion::gt('1.2.3', '9.8.7'); //false\nversion::lt('1.2.3', '9.8.7'); //true\n```\n\n## Versions\n\nA version is the following things, in this order:\n\n* a number (Major)\n* a period\n* a number (minor)\n* a period\n* a number (patch)\n* OPTIONAL: a hyphen, followed by a number (build)\n* OPTIONAL: a collection of pretty much any non-whitespace characters\n  (tag)\n\nA leading `\"=\"` or `\"v\"` character is stripped off and ignored.\n\n## Comparisons\n\nThe ordering of versions is done using the following algorithm, given\ntwo versions and asked to find the greater of the two:\n\n* If the majors are numerically different, then take the one\n  with a bigger major number. `2.3.4 > 1.3.4`\n* If the minors are numerically different, then take the one\n  with the bigger minor number. `2.3.4 > 2.2.4`\n* If the patches are numerically different, then take the one with the\n  bigger patch number. `2.3.4 > 2.3.3`\n* If only one of them has a build number, then take the one with the\n  build number.  `2.3.4-0 > 2.3.4`\n* If they both have build numbers, and the build numbers are numerically\n  different, then take the one with the bigger build number.\n  `2.3.4-10 > 2.3.4-9`\n* If only one of them has a tag, then take the one without the tag.\n  `2.3.4 > 2.3.4-beta`\n* If they both have tags, then take the one with the lexicographically\n  larger tag.  `2.3.4-beta > 2.3.4-alpha`\n* At this point, they're equal.\n\n## Ranges\n\nThe following range styles are supported:\n\n* `>1.2.3` Greater than a specific version.\n* `<1.2.3` Less than\n* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`\n* `~1.2.3` := `>=1.2.3 <1.3.0`\n* `~1.2` := `>=1.2.0 <2.0.0`\n* `~1` := `>=1.0.0 <2.0.0`\n* `1.2.x` := `>=1.2.0 <1.3.0`\n* `1.x` := `>=1.0.0 <2.0.0`\n\nRanges can be joined with either a space (which implies \"and\") or a\n`||` (which implies \"or\").\n\n## Functions\n\n* `$version->valid()`: Return the parsed version, or null if it's not valid.\n* `$version->inc($type)`: Return the version incremented by the release type\n  (major, minor, patch, or build), or null if an invalid release type is provided.\n\n### Comparison\n\n* `version::gt($v1, $v2)`: `v1 > v2`\n* `version::gte($v1, $v2)`: `v1 >= v2`\n* `version::lt($v1, $v2)`: `v1 < v2`\n* `version::lte($v1, $v2)`: `v1 <= v2`\n* `version::eq($v1, $v2)`: `v1 == v2` This is true if they're logically equivalent,\n  even if they're not the exact same string.  You already know how to\n  compare strings.\n* `version::neq($v1, $v2)`: `v1 != v2` The opposite of eq.\n* `version::cmp($v1, $comparator, $v2)`: Pass in a comparison string, and it'll call\n  the corresponding function above.  `\"===\"` and `\"!==\"` do simple\n  string comparison, but are included for completeness.  Throws if an\n  invalid comparison string is provided.\n* `version::compare($v1, $v2)`: Return 0 if `v1 == v2`, 1 if `v1 > v2`, or -1 if\n  `v1 < v2`.  Sorts in ascending order if passed to [`usort()`](http://php.net/manual/en/function.usort.php)\n* `version::rcompare($v1, $v2)`: The reverse of compare.  Sorts an array of versions\n  in descending order when passed to [`usort()`](http://php.net/manual/en/function.usort.php).\n\n\n### Ranges\n\n* `$expression->validRange()`: Return the valid range or `null` if it's not valid\n* `$version->satisfies($range)`: Return `true` if the version satisfies the range.\n* `$expression->maxSatisfying($versions)`: Return the highest version in the array\n  that satisfies the range, or `null` if none of them do.\n\n## Thanks to\n\nAll contributors (https://github.com/vierbergenlars/php-semver/graphs/contributors)\n\n[@isaacs](https://github.com/isaacs) and other contributors to [node-semver](https://github.com/isaacs/node-semver)\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/bin/semver",
    "content": "#!/usr/bin/env php\n<?php\n\nnamespace vierbergenlars\\SemVer\\Application\\SemVer;\n\nrequire __DIR__ . '/../vendor/autoload.php';\n\nuse vierbergenlars\\SemVer\\version;\nuse vierbergenlars\\SemVer\\expression;\nuse vierbergenlars\\SemVer\\SemVerException;\n\n$version = false;\n$range = array();\n$increment = false;\n\n// Get all arguments\nwhile (\\count($argv) > 0) {\n    $arg = \\array_shift($argv);\n    switch ($arg) {\n        case '-v':\n        case '--version':\n            $version[] = \\array_shift($argv);\n            break;\n        case '-r':\n        case '--range':\n            $range[] = \\array_shift($argv);\n            break;\n        case '-i':\n        case '--increment':\n            $increment = \\array_shift($argv);\n            break;\n        case '-?':\n        case '-h':\n        case '--help':\n            help();\n            break;\n    }\n}\nmain();\n\nfunction help() {\n    $e = array(\n        'Usage: semver -v|--version <version> [options]'\n        , ''\n        , '  -r <range>\t\t\tTest if version satisfies the supplied range.'\n        , '  --range <range>'\n        , '  -i [major|minor|patch|build]\tIncrement the given version number.'\n        , '  --increment [major|minor|patch|build]'\n        , ''\n        , 'Multiple versions or ranges may be supplied.'\n        , ''\n        , 'Program exits successfully if any valid version satisfies'\n        , 'all supplied ranges, and prints all satisfying versions.'\n        , ''\n        , 'If no versions are valid, or ranges are not satisfied,'\n        , 'then exits failure.'\n        , ''\n        , 'Versions are printed in ascending order, so supplying'\n        , 'multiple versions to the utility will just sort them.'\n    );\n    echo \\implode(PHP_EOL, $e);\n    exit;\n}\n\nfunction main() {\n    global $version, $range, $increment;\n    if ($increment !== false) {\n        increment($version[0], $increment);\n    }\n    if ($version !== false) {\n        filter($version, $range);\n    }\n    help();\n}\n\nfunction fail($message = '') {\n    fwrite(STDERR, $message);\n    exit(1);\n}\n\nfunction increment($version, $what) {\n    if (\\file_exists($version))\n        $version = \\file_get_contents($version);\n    if ($version == '-')\n        $version = \\fgets(STDIN);\n    try {\n        $v = new version($version);\n        echo $v->inc($what);\n        exit;\n    } catch (SemVerException $e) {\n        fail($e->getMessage());\n    }\n}\n\nfunction filter($versions, $ranges) {\n    if (\\file_exists($versions[0]))\n        $versions = \\file($versions[0], \\FILE_IGNORE_NEW_LINES | \\FILE_SKIP_EMPTY_LINES);\n    if ($versions[0] == '-') {\n        unset($versions[0]);\n        while ($version = \\fgets(\\STDIN)) {\n            $versions[] = $version;\n        }\n    }\n    $matching_versions = array();\n    foreach ($versions as $version) {\n        $ok = true;\n        try {\n            $v = new version($version);\n            foreach ($ranges as $range) {\n                if ($v->satisfies(new expression($range)))\n                    continue;\n                $ok = false;\n                break;\n            }\n            if ($ok)\n                $matching_versions[] = $v;\n        } catch (SemVerException $e) {\n\n        }\n    }\n    \\usort($matching_versions, '\\\\vierbergenlars\\\\SemVer\\\\version::compare');\n    foreach ($matching_versions as $version) {\n        echo $version . PHP_EOL;\n    }\n    if (\\count($matching_versions) == 0)\n        fail();\n    exit;\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/bin/update-versions",
    "content": "#!/usr/bin/env php\n<?php\n\nnamespace vierbergenlars\\SemVer\\Application\\UpdateVersions;\n\nrequire __DIR__ . '/../vendor/autoload.php';\n\nuse vierbergenlars\\SemVer\\version;\nuse vierbergenlars\\SemVer\\expression;\nuse vierbergenlars\\SemVer\\SemVerException;\n\n//Defaults\n/**\n * Input file containing the version\n * @var string\n */\n$input = 'composer.json';\n/**\n * Array of paths to write to\n * @var array\n */\n$writeto = array();\n/**\n * Root directory\n * @var string\n */\n$root = '.';\n/**\n * Do not do anything\n * @var bool\n */\n$dry_run = false;\n/**\n * Shell command to execute for each updated file\n * @var string\n */\n$shell = NULL;\n// Get all arguments\nwhile (\\count($argv) > 0) {\n    $arg = \\array_shift($argv);\n    switch ($arg) {\n        case '-p':\n        case '--package':\n            $input = \\array_shift($argv);\n            break;\n        case '-s':\n        case '--source':\n            $writeto[] = \\array_shift($argv);\n            break;\n        case '-b':\n        case '--base':\n            $root = \\array_shift($argv);\n            break;\n        case '--dry-run':\n            $dry_run = true;\n            break;\n        case '--shell':\n            $shell = \\array_shift($argv);\n            break;\n        case '-h':\n        case '--help':\n            help();\n    }\n}\n//Defaults writeto\nif ($writeto === array()) {\n    $writeto = array('src', 'bin');\n}\n//Add root paths\n$input = $root . '/' . $input;\nforeach ($writeto as &$write) {\n    $write = $root . '/' . $write;\n}\n//Read those JSON files\nif (!\\file_exists($input))\n    fail('Package file does not exist');\n$input = \\json_decode(\\file_get_contents($input), true);\nif (!$input) {\n    fail('Invalid JSON file!');\n}\n//Initialize the version from package file\ntry {\n    $version = new version($input['version']);\n} catch (SemVerException $e) {\n    fail($e->getMessage());\n}\n$version = $version->getString();\nforeach ($writeto as $output) {\n    $dir = new \\RecursiveIteratorIterator(new \\RecursiveDirectoryIterator($output));\n    foreach ($dir as $file) {\n        if (\\preg_match('/[\\\\\\\\\\\\/]\\\\./', $file))\n            continue; //Ignore . directories\n        $contents1 = \\file_get_contents($file);\n        $contents2 = \\str_replace(array('2.0.0--', '{{{' . 'version}}}'), $version, $contents1);\n        if ($contents1 != $contents2) {\n            fwrite(\\STDOUT, 'Writing version information to file ' . $file . \\PHP_EOL);\n            if ($shell !== null) {\n                \\system($shell . ' \"' . $file . '\"', $exit_code);\n                if ($exit_code != 0)\n                    fail('Subshell exited ' . $exit_code);\n            }\n            if ($dry_run) {\n                \\fwrite(\\STDOUT, '\\\\_Not writing to disk' . \\PHP_EOL);\n            } else {\n                \\file_put_contents($file, $contents2);\n            }\n        }\n    }\n}\n\nfunction help() {\n    $e = array(\n        'Usage: update-versions [options]'\n        , ''\n        , '  -p <composerfile>          Use this file as composer.json file'\n        , '  --package <composerfile>'\n        , '  -s <dir>                   Add directory to sources to scan. May be repeated.'\n        , '  --source <dir>'\n        , '  -b <dir>                   Use this directory as base directory.'\n        , '  --base <dir>'\n        , '  --shell <command>          Execute <command> for each changed file.'\n        , '  --dry-run                  Do not write files.'\n        , ''\n        , 'This program exits 0 on success or 1 on failure.'\n        , 'Defaults to \"--package composer.json --source src --source bin --base .\"'\n    );\n    echo \\implode(PHP_EOL, $e);\n    exit;\n}\n\nfunction fail($message = '') {\n    \\fwrite(\\STDERR, $message . \\PHP_EOL);\n    exit(1);\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/composer.json",
    "content": "{\n    \"name\": \"vierbergenlars/php-semver\",\n    \"description\": \"The Semantic Versioner for PHP\",\n    \"keywords\": [\"semver\", \"versioning\", \"semantic\"],\n    \"type\": \"library\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Lars Vierbergen\",\n            \"email\": \"vierbergenlars@gmail.com\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=5.3.0\"\n    },\n    \"require-dev\": {\n        \"phpunit/phpunit\": \"~4\"\n    },\n    \"autoload\": {\n        \"psr-0\": {\n            \"vierbergenlars\\\\SemVer\\\\\": \"src/\",\n            \"vierbergenlars\\\\LibJs\\\\\":  \"src/\"\n        },\n        \"classmap\": [\n            \"src/vierbergenlars/SemVer/internal.php\"\n        ]\n    },\n    \"bin\": [\n        \"bin/semver\",\n        \"bin/update-versions\"\n    ]\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/definitions",
    "content": "RemoteCP Versioning format\r\n==========================\r\n##x.y.z format\r\n\r\n1. x is the major version number for backwards incompatible changes (e.g. removed functions)\r\n2. y is the minor version number for backwards compatible changes (e.g. added functions)\r\n3. z is the patch number, for bug fixes\r\n\r\n##Comparators\r\nLower version: <\r\nHigher version: >\r\nLower or equal version: <=\r\nHigher or equal version: >=\r\nx or * as a wildcard\r\n  e.g.: 1.x.x\t\t>= 1.0.0 < 2.0.0\r\n        1.2.*\t\t>= 1.2.0 < 1.3.0\r\nA range can be expressed with -\r\n  e.g.: 1.0.0 - 1.2.3\t\t>=1.0.0 <1.2.3\r\n        1.2.0 - 2.0.0\t\t>=1.2.0 <2.0.0\r\nA range can be expressed by omitting lower order numbers\r\n  e.g.: 1\t\t>=1.0.0 <2.0.0\r\n        1.2\t\t>=1.2.0 <1.3.0\r\nA range can be expressed with ~\r\n  e.g.: ~1\t\t>=1.0.0 <2.0.0\r\n        ~1.2\t>=1.2.0 <1.3.0\r\n        ~1.2.3\t>=1.2.3 <1.3.0\r\n\r\n##Logic\r\nTwo or more comparators in one string with only spaces between them: AND\r\n||: OR"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/license.md",
    "content": "# The MIT License (MIT)\n\n```\nCopyright (c) 2013 Lars Vierbergen\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/phpunit.xml.dist",
    "content": "<phpunit bootstrap=\"vendor/autoload.php\">\n\t<testsuite name=\"Tests\">\n\t\t<directory>./tests</directory>\n\t</testsuite>\n\n\t<filter>\n\t\t<whitelist>\n\t\t\t<directory suffix=\".php\">./src</directory>\n\t\t</whitelist>\n\t</filter>\n\n\t<logging>\n\t\t<log type=\"coverage-html\" target=\"./log/report\" charset=\"UTF-8\" yui=\"true\" highlight=\"true\" lowUpperBound=\"50\" highLowerBound=\"80\" />\n\t\t<log type=\"coverage-text\" target=\"./log/coverage.txt\"/>\n\t\t<log type=\"coverage-clover\" target=\"./log/coverage.xml\"/>\n\t\t<log type=\"testdox-html\" target=\"./log/testdox.html\" />\n\t</logging>\n</phpunit>"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/JObject.php",
    "content": "<?php\n\n/**\n * Copyright (c) 2013 Lars Vierbergen\n * MIT licensed\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nnamespace vierbergenlars\\LibJs;\n\nclass JObject\n{\n    /**\n     *\n     * @param mixed $something\n     * @return \\vierbergenlars\\LibJs\\JString|\\vierbergenlars\\LibJs\\JSArray|mixed\n     * @private\n     */\n    public function _convert($something)\n    {\n        if(is_string($something)) {\n            return new JString($something);\n        } elseif(is_array($something)) {\n            return new JSArray($something);\n        } else {\n            return $something;\n        }\n    }\n\n    public function toString()\n    {\n        return new JString((string)$this);\n    }\n\n    public function valueOf()\n    {\n        return (string)$this;\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/JSArray.php",
    "content": "<?php\n\n/**\n * Copyright (c) 2013 Lars Vierbergen\n * MIT licensed\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nnamespace vierbergenlars\\LibJs;\n\nclass JSArray extends JObject implements \\ArrayAccess, \\Iterator\n{\n    /**\n     *\n     * @var array\n     */\n    private $array;\n\n    /**\n     *\n     * @var int\n     * @public\n     */\n    private $length = null;\n\n    /**\n     *\n     * @param array $arr\n     */\n    public function __construct(array $arr = array())\n    {\n        $this->array = $arr;\n    }\n\n    /**\n     *\n     * @param \\Closure $func\n     * @return JSArray\n     */\n    public function filter(\\Closure $func)\n    {\n        $finalArray = new JSArray();\n        foreach($this->array as $key => $value) {\n            $key = $this->_convert($key);\n            $value = $this->_convert($value);\n            $ret = $func($value, $key, $this);\n            if($ret)\n                $finalArray->push($value);\n        }\n        return $finalArray;\n    }\n\n    public function JSforEach(\\Closure $func)\n    {\n        $a = $this->array;\n        foreach($this->array as $key=>$val) {\n            $func($this->_convert($val), $this->_convert($key), $this);\n        }\n    }\n\n    /**\n     *\n     * @param JString $c\n     * @return JString\n     */\n    public function join($c)\n    {\n        return new JString(implode($c, $this->array));\n    }\n\n    /**\n     *\n     * @return JSArray\n     */\n    public function reverse()\n    {\n        return new self(array_reverse($this->array));\n    }\n\n    /**\n     *\n     * @param \\Closure $compareFunction\n     * @return JSArray\n     */\n    public function sort(\\Closure $compareFunction = null)\n    {\n        $a = $this->array;\n        if($compareFunction) {\n            usort($a, $compareFunction);\n        } else {\n            sort($a);\n        }\n\n        return new self($a);\n    }\n\n    /**\n     *\n     * @param \\Closure $func\n     * @return JSArray\n     */\n    public function map(\\Closure $func)\n    {\n        $that = $this;\n        $wrap = function($str) use($func, $that) {\n            $str = $that->_convert($str);\n            return $func($str);\n        };\n        return new self(array_map($wrap, $this->array));\n    }\n\n    /**\n     * @return int\n     */\n    public function push()\n    {\n        foreach(func_get_args() as $arg)\n        {\n            $this->array[] = $arg;\n        }\n        return $this->length = count($this->array);\n    }\n\n    public function __get($name)\n    {\n        switch($name) {\n            case 'length':\n                if($this->length !== null)\n                    return $this->length;\n                return $this->length = count($this->array);\n        }\n    }\n\n\n    public function current()\n    {\n        return $this->_convert(current($this->array));\n    }\n\n    public function key()\n    {\n        return $this->_convert(key($this->array));\n    }\n\n    public function next()\n    {\n        return $this->_convert(next($this->array));\n    }\n\n    public function offsetExists($offset)\n    {\n        return isset($this->array[$offset]);\n    }\n\n    public function offsetGet($offset)\n    {\n        if(!$this->offsetExists($offset))\n            return null;\n        return $this->_convert($this->array[$offset]);\n    }\n\n    public function offsetSet($offset, $value)\n    {\n        $this->array[$offset] = $value;\n    }\n\n    public function offsetUnset($offset)\n    {\n        unset($this->array[$offset]);\n    }\n\n    public function rewind()\n    {\n        return reset($this->array);\n    }\n\n    public function valid()\n    {\n        return each($this->array)!== false;\n    }\n\n    public function valueOf()\n    {\n        return $this->array;\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/JString.php",
    "content": "<?php\n\n/**\n * Copyright (c) 2013 Lars Vierbergen\n * MIT licensed\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nnamespace vierbergenlars\\LibJs;\n\nclass JString extends JObject implements \\ArrayAccess\n{\n    /**\n     * Wrapped string\n     * @var string\n     */\n    private $str;\n\n    /**\n     *\n     * @param string $str\n     */\n    public function __construct($str)\n    {\n        $this->str = (string)$str;\n    }\n\n    /**\n     *\n     * @param int $pos\n     * @return string\n     */\n    public function charAt($pos)\n    {\n        if(isset($this->str[$pos]))\n            return $this->str[$pos];\n        return '';\n    }\n\n    /**\n     *\n     * @param int $pos\n     * @return int\n     */\n    public function charCodeAt($pos)\n    {\n        if(!isset($this->str[$pos]))\n            return NAN;\n        return (int)ord($this->charAt($pos));\n    }\n\n    /**\n     *\n     * @return JString\n     */\n    public function concat()\n    {\n        $concat = $this->str;\n        $strings = func_get_args();\n        foreach($strings as $str) {\n            $concat.=$str;\n        }\n        return new self($concat);\n    }\n\n    /**\n     *\n     * @param string|RegExp $regex\n     * @return JSArray\n     */\n    public function match($regex)\n    {\n        if(!$regex instanceof RegExp)\n            $regex = new RegExp((string)$regex);\n        $ret = $regex->exec($this);\n        if($ret&&!$regex->global) {\n            $ret->input = $this;\n        }\n        return $ret;\n    }\n\n    /**\n     *\n     * @param RegExp|string $regexOrSubstr\n     * @param \\Closure|string $newSubstrOrFunction\n     * @return JString\n     */\n    public function replace($regexOrSubstr, $newSubstrOrFunction)\n    {\n        if($regexOrSubstr instanceof RegExp) {\n            if($newSubstrOrFunction instanceof \\Closure) {\n                $wrap = function($matches)use($newSubstrOrFunction) {\n                    $matches = array_map(function($s) {\n                        return new JString($s);\n                    }, $matches);\n                    return call_user_func_array($newSubstrOrFunction, $matches);\n                };\n                return new self(preg_replace_callback(\n                    $regexOrSubstr->_pregSource,\n                    $wrap,\n                    (string)$this\n                ));\n            } else {\n                return new self(preg_replace(\n                    $regexOrSubstr->_pregSource,\n                    $newSubstrOrFunction,\n                    (string)$this\n                ));\n            }\n        } else {\n            return new self(str_replace($regexOrSubstr, $newSubstrOrFunction, (string)$this));\n        }\n    }\n\n    /**\n     *\n     * @param string|JString|RegExp $c\n     * @return JSArray\n     */\n    public function split($c)\n    {\n        if($c instanceof RegExp) {\n            $ret = preg_split($c->_pregSource, (string)$this);\n        } else {\n            $ret = explode((string)$c,(string)$this);\n        }\n        return new JSArray($ret);\n    }\n\n    /**\n     *\n     * @return JString\n     */\n    public function toLowerCase()\n    {\n        return new self(strtolower((string)$this));\n    }\n\n    /**\n     *\n     * @return JString\n     */\n    public function toString()\n    {\n        return $this;\n    }\n\n    /**\n     *\n     * @return JString\n     */\n    public function toUpperCase()\n    {\n        return new self(strtoupper((string)$this));\n    }\n\n    /**\n     *\n     * @return JString\n     */\n    public function trim()\n    {\n        return new self(trim((string)$this));\n    }\n\n    /**\n     *\n     * @return string\n     */\n    public function valueOf()\n    {\n        return (string)$this;\n    }\n\n    /**\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->str;\n    }\n\n    public function __get($name)\n    {\n        switch($name) {\n            case 'length':\n                return strlen($this->str);\n        }\n    }\n\n    public function offsetExists($offset)\n    {\n        return isset($this->str[$offset]);\n    }\n\n    public function offsetGet($offset)\n    {\n        return $this->str[$offset];\n    }\n\n    public function offsetSet($offset, $value)\n    {\n        $this->str[$offset] = $value;\n    }\n\n    public function offsetUnset($offset)\n    {\n        throw new \\LogicException('Cannot unset a position in a string');\n    }\n\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/RegExp.php",
    "content": "<?php\n\n/**\n * Copyright (c) 2013 Lars Vierbergen\n * MIT licensed\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nnamespace vierbergenlars\\LibJs;\n\nclass RegExp extends JObject\n{\n    /**\n     *\n     * @var string\n     */\n    private $regex;\n\n    /**\n     *\n     * @var string\n     * @internal\n     */\n    public $_pregSource = null;\n\n    /**\n     *\n     * @var boolean\n     */\n    public $global = false;\n\n    /**\n     *\n     * @param string $regex\n     * @param string $flags\n     */\n    public function __construct($regex, $flags = '')\n    {\n        $this->regex = '/'.$regex.'/'.$flags;\n        $this->_pregSource = '/'.$regex.'/';\n        if(strpos($flags, 's') !== false)\n            $this->global = true;\n    }\n\n    /**\n     *\n     * @param string|JString $str\n     */\n    public function exec($str)\n    {\n        if($this->global) {\n            if(!preg_match_all($this->_pregSource, (string)$str, $matches))\n                return null;\n        } else {\n            if(!preg_match($this->_pregSource, (string)$str, $matches))\n                return null;\n        }\n        return new JSArray($matches);\n    }\n\n    /**\n     *\n     * @param string|JString $str\n     */\n    public function test($str)\n    {\n        if($this->global) {\n            return preg_match_all($this->_pregSource, (string)$str);\n        } else {\n            return preg_match($this->_pregSource, (string)$str);\n        }\n    }\n\n    public function valueOf()\n    {\n        return $this->regex;\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Util.php",
    "content": "<?php\n\n/**\n * Copyright (c) 2013 Lars Vierbergen\n * MIT licensed\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nnamespace vierbergenlars\\LibJs;\n\nclass Util\n{\n    private function __construct()\n    {\n\n    }\n\n    public static function JSor()\n    {\n        foreach(func_get_args() as $arg) {\n            if($arg instanceof JString)\n                $arg = $arg->valueOf();\n            if($arg)\n                return $arg;\n        }\n        return 0;\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/SemVerException.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer;\n\nclass SemVerException extends \\RuntimeException\n{\n    protected $version = null;\n\n    public function __construct($message, $version = null)\n    {\n        $this->version = $version;\n        parent::__construct($message . ' [[' . $version . ']]');\n    }\n\n    public function getVersion()\n    {\n        return $this->version;\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/expression.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer;\nuse vierbergenlars\\SemVer\\Internal\\Range;\nuse vierbergenlars\\SemVer\\Internal\\G;\nuse vierbergenlars\\LibJs\\JSArray;\n\nclass expression\n{\n    /**\n     *\n     * @var Range\n     */\n    private $range;\n\n    /**\n     * standardizes the comparator/range/whatever-string to chunks\n     * @param string $versions\n     */\n    public function __construct($versions, $loose = false)\n    {\n        try {\n            $this->range = new Range($versions, $loose);\n        } catch(\\Exception $e) {\n            throw new SemVerException($e->getMessage(), $e->getCode(), $e);\n        }\n    }\n\n    /**\n     * Checks ifthis range is satisfied by the given version\n     * @param  version $version\n     * @return boolean\n     */\n    public function satisfiedBy(version $version)\n    {\n        return $this->range->test($version);\n    }\n\n    /**\n     * Get the whole or object as a string\n     * @return string\n     */\n    public function getString()\n    {\n        return (string)$this->range->toString();\n    }\n\n    /**\n     * Get the object as an expression\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->getString();\n    }\n\n    /**\n     * Get the object as a range expression\n     * @return string\n     */\n    public function validRange()\n    {\n        return $this->getString();\n    }\n\n    /**\n     * Find the maximum satisfying version\n     * @param  array|string                        $versions An array of version objects or version strings, one version string\n     * @return \\vierbergenlars\\SemVer\\version|null\n     */\n    public function maxSatisfying($versions, $loose = false)\n    {\n        if(!is_array($versions))\n            $versions = array($versions);\n        return new version((string)G::maxSatisfying(new JSArray($versions), $this->range, $loose));\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer\\Internal;\nuse vierbergenlars\\LibJs\\JSArray;\nuse vierbergenlars\\LibJs\\JString;\nuse vierbergenlars\\LibJs\\RegExp;\nuse vierbergenlars\\LibJs\\JObject;\nuse vierbergenlars\\LibJs\\Util;\n\nclass G\n{\n    public static function __callStatic($name, $arguments)\n    {\n        return call_user_func_array(__NAMESPACE__.'\\\\'.$name, $arguments);\n    }\n}\n\nclass Exports\n{\n    static public $re = array();\n    static public $src = array();\n    const SEMVER_SPEC_VERSION = '2.0.0';\n}\n\n$R = 0;\n\n// The following Regular Expressions can be used for tokenizing,\n// validating, and parsing SemVer version strings.\n\n// ## Numeric Identifier\n// A single `0`, or a non-zero digit followed by zero or more digits.\n\ndefine(__NAMESPACE__.'\\\\NUMERICIDENTIFIER', $R++);\nExports::$src[NUMERICIDENTIFIER] = '0|[1-9]\\\\d*';\ndefine(__NAMESPACE__.'\\\\NUMERICIDENTIFIERLOOSE', $R++);\nExports::$src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';\n\n\n// ## Non-numeric Identifier\n// Zero or more digits, followed by a letter or hyphen, and then zero or\n// more letters, digits, or hyphens.\n\ndefine(__NAMESPACE__.'\\\\NONNUMERICIDENTIFIER', $R++);\nExports::$src[NONNUMERICIDENTIFIER] = '\\\\d*[a-zA-Z-][a-zA-Z0-9-]*';\n\n\n// ## Main Version\n// Three dot-separated numeric identifiers.\n\ndefine(__NAMESPACE__.'\\\\MAINVERSION', $R++);\nExports::$src[MAINVERSION] = '(' . Exports::$src[NUMERICIDENTIFIER] . ')\\\\.' .\n                   '(' . Exports::$src[NUMERICIDENTIFIER] . ')\\\\.' .\n                   '(' . Exports::$src[NUMERICIDENTIFIER] . ')';\n\ndefine(__NAMESPACE__.'\\\\MAINVERSIONLOOSE', $R++);\nExports::$src[MAINVERSIONLOOSE] = '(' . Exports::$src[NUMERICIDENTIFIERLOOSE] . ')\\\\.' .\n                        '(' . Exports::$src[NUMERICIDENTIFIERLOOSE] . ')\\\\.' .\n                        '(' . Exports::$src[NUMERICIDENTIFIERLOOSE] . ')';\n\n// ## Pre-release Version Identifier\n// A numeric identifier, or a non-numeric identifier.\n\ndefine(__NAMESPACE__.'\\\\PRERELEASEIDENTIFIER', $R++);\nExports::$src[PRERELEASEIDENTIFIER] = '(?:' . Exports::$src[NUMERICIDENTIFIER] .\n                            '|' . Exports::$src[NONNUMERICIDENTIFIER] . ')';\n\ndefine(__NAMESPACE__.'\\\\PRERELEASEIDENTIFIERLOOSE', $R++);\nExports::$src[PRERELEASEIDENTIFIERLOOSE] = '(?:' . Exports::$src[NUMERICIDENTIFIERLOOSE] .\n                                 '|' . Exports::$src[NONNUMERICIDENTIFIER] . ')';\n\n\n// ## Pre-release Version\n// Hyphen, followed by one or more dot-separated pre-release version\n// identifiers.\n\ndefine(__NAMESPACE__.'\\\\PRERELEASE', $R++);\nExports::$src[PRERELEASE] = '(?:-(' . Exports::$src[PRERELEASEIDENTIFIER] .\n                  '(?:\\\\.' . Exports::$src[PRERELEASEIDENTIFIER] . ')*))';\n\ndefine(__NAMESPACE__.'\\\\PRERELEASELOOSE', $R++);\nExports::$src[PRERELEASELOOSE] = '(?:-?(' . Exports::$src[PRERELEASEIDENTIFIERLOOSE] .\n                       '(?:\\\\.' . Exports::$src[PRERELEASEIDENTIFIERLOOSE] . ')*))';\n\n// ## Build Metadata Identifier\n// Any combination of digits, letters, or hyphens.\n\ndefine(__NAMESPACE__.'\\\\BUILDIDENTIFIER', $R++);\nExports::$src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';\n\n// ## Build Metadata\n// Plus sign, followed by one or more period-separated build metadata\n// identifiers.\n\ndefine(__NAMESPACE__.'\\\\BUILD', $R++);\nExports::$src[BUILD] = '(?:\\\\+(' . Exports::$src[BUILDIDENTIFIER] .\n             '(?:\\\\.' . Exports::$src[BUILDIDENTIFIER] . ')*))';\n\n\n// ## Full Version String\n// A main version, followed optionally by a pre-release version and\n// build metadata.\n\n// Note that the only major, minor, patch, and pre-release sections of\n// the version string are capturing groups.  The build metadata is not a\n// capturing group, because it should not ever be used in version\n// comparison.\n\ndefine(__NAMESPACE__.'\\\\FULL', $R++);\ndefine(__NAMESPACE__.'\\\\FULLPLAIN','v?' . Exports::$src[MAINVERSION] .\n                Exports::$src[PRERELEASE] . '?' .\n                Exports::$src[BUILD] . '?');\n\nExports::$src[FULL] = '^' . FULLPLAIN . '$';\n\n// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.\n// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty\n// common in the npm registry.\ndefine(__NAMESPACE__.'\\\\LOOSEPLAIN', '[v=\\\\s]*' . Exports::$src[MAINVERSIONLOOSE] .\n                 Exports::$src[PRERELEASELOOSE] . '?' .\n                 Exports::$src[BUILD] . '?');\n\ndefine(__NAMESPACE__.'\\\\LOOSE', $R++);\nExports::$src[LOOSE] = '^' . LOOSEPLAIN . '$';\n\ndefine(__NAMESPACE__.'\\\\GTLT', $R++);\nExports::$src[GTLT] = '((?:<|>)?=?)';\n\n// Something like \"2.*\" or \"1.2.x\".\n// Note that \"x.x\" is a valid xRange identifer, meaning \"any version\"\n// Only the first item is strictly required.\ndefine(__NAMESPACE__.'\\\\XRANGEIDENTIFIERLOOSE', $R++);\nExports::$src[XRANGEIDENTIFIERLOOSE] = Exports::$src[NUMERICIDENTIFIERLOOSE] . '|x|X|\\\\*';\ndefine(__NAMESPACE__.'\\\\XRANGEIDENTIFIER', $R++);\nExports::$src[XRANGEIDENTIFIER] = Exports::$src[NUMERICIDENTIFIER] . '|x|X|\\\\*';\n\ndefine(__NAMESPACE__.'\\\\XRANGEPLAIN', $R++);\nExports::$src[XRANGEPLAIN] = '[v=\\\\s]*(' . Exports::$src[XRANGEIDENTIFIER] . ')' .\n                   '(?:\\\\.(' . Exports::$src[XRANGEIDENTIFIER] . ')' .\n                   '(?:\\\\.(' . Exports::$src[XRANGEIDENTIFIER] . ')' .\n                   '(?:(' . Exports::$src[PRERELEASE] . ')' .\n                   ')?)?)?';\n\ndefine(__NAMESPACE__.'\\\\XRANGEPLAINLOOSE', $R++);\nExports::$src[XRANGEPLAINLOOSE] = '[v=\\\\s]*(' . Exports::$src[XRANGEIDENTIFIERLOOSE] . ')' .\n                        '(?:\\\\.(' . Exports::$src[XRANGEIDENTIFIERLOOSE] . ')' .\n                        '(?:\\\\.(' . Exports::$src[XRANGEIDENTIFIERLOOSE] . ')' .\n                        '(?:(' . Exports::$src[PRERELEASELOOSE] . ')' .\n                        ')?)?)?';\n\n// >=2.x, for example, means >=2.0.0-0\n// <1.x would be the same as \"<1.0.0-0\", though.\ndefine(__NAMESPACE__.'\\\\XRANGE', $R++);\nExports::$src[XRANGE] = '^' . Exports::$src[GTLT] . '\\\\s*' . Exports::$src[XRANGEPLAIN] . '$';\ndefine(__NAMESPACE__.'\\\\XRANGELOOSE', $R++);\nExports::$src[XRANGELOOSE] = '^' . Exports::$src[GTLT] . '\\\\s*' . Exports::$src[XRANGEPLAINLOOSE] . '$';\n\n// Tilde ranges.\n// Meaning is \"reasonably at or greater than\"\ndefine(__NAMESPACE__.'\\\\LONETILDE', $R++);\nExports::$src[LONETILDE] = '(?:~>?)';\n\ndefine(__NAMESPACE__.'\\\\TILDETRIM', $R++);\nExports::$src[TILDETRIM] = '(\\\\s*)' . Exports::$src[LONETILDE] . '\\\\s+';\nExports::$re[TILDETRIM] = new RegExp(Exports::$src[TILDETRIM], 'g');\ndefine(__NAMESPACE__.'\\\\tildeTrimReplace', '$1~');\n\ndefine(__NAMESPACE__.'\\\\TILDE', $R++);\nExports::$src[TILDE] = '^' . Exports::$src[LONETILDE] . Exports::$src[XRANGEPLAIN] . '$';\ndefine(__NAMESPACE__.'\\\\TILDELOOSE', $R++);\nExports::$src[TILDELOOSE] = '^' . Exports::$src[LONETILDE] . Exports::$src[XRANGEPLAINLOOSE] . '$';\n\n// Caret ranges.\n// Meaning is \"at least and backwards compatible with\"\ndefine(__NAMESPACE__.'\\\\LONECARET', $R++);\nExports::$src[LONECARET] = '(?:\\\\^)';\n\ndefine(__NAMESPACE__.'\\\\CARETTRIM', $R++);\nExports::$src[CARETTRIM] = '(\\\\s*)' . Exports::$src[LONECARET] . '\\\\s+';\nExports::$re[CARETTRIM] = new RegExp(Exports::$src[CARETTRIM], 'g');\ndefine(__NAMESPACE__.'\\\\caretTrimReplace', '$1^');\n\ndefine(__NAMESPACE__.'\\\\CARET', $R++);\nExports::$src[CARET] = '^' . Exports::$src[LONECARET] . Exports::$src[XRANGEPLAIN] . '$';\ndefine(__NAMESPACE__.'\\\\CARETLOOSE', $R++);\nExports::$src[CARETLOOSE] = '^' . Exports::$src[LONECARET] . Exports::$src[XRANGEPLAINLOOSE] . '$';\n\n// A simple gt/lt/eq thing, or just \"\" to indicate \"any version\"\ndefine(__NAMESPACE__.'\\\\COMPARATORLOOSE', $R++);\nExports::$src[COMPARATORLOOSE] = '^' . Exports::$src[GTLT] . '\\\\s*(' . LOOSEPLAIN . ')$|^$';\ndefine(__NAMESPACE__.'\\\\COMPARATOR', $R++);\nExports::$src[COMPARATOR] = '^' . Exports::$src[GTLT] . '\\\\s*(' . FULLPLAIN . ')$|^$';\n\n\n// An expression to strip any whitespace between the gtlt and the thing\n// it modifies, so that `> 1.2.3` ==> `>1.2.3`\ndefine(__NAMESPACE__.'\\\\COMPARATORTRIM', $R++);\nExports::$src[COMPARATORTRIM] = '(\\\\s*)' . Exports::$src[GTLT] .\n                      '\\\\s*(' . LOOSEPLAIN . '|' . Exports::$src[XRANGEPLAIN] . ')';\n\n// this one has to use the /g flag\nExports::$re[COMPARATORTRIM] = new RegExp(Exports::$src[COMPARATORTRIM], 'g');\ndefine(__NAMESPACE__.'\\\\comparatorTrimReplace', '$1$2$3');\n\n\n// Something like `1.2.3 - 1.2.4`\n// Note that these all use the loose form, because they'll be\n// checked against either the strict or loose comparator form\n// later.\ndefine(__NAMESPACE__.'\\\\HYPHENRANGE', $R++);\nExports::$src[HYPHENRANGE] = '^\\\\s*(' . Exports::$src[XRANGEPLAIN] . ')' .\n                   '\\\\s+-\\\\s+' .\n                   '(' . Exports::$src[XRANGEPLAIN] . ')' .\n                   '\\\\s*$';\n\ndefine(__NAMESPACE__.'\\\\HYPHENRANGELOOSE', $R++);\nExports::$src[HYPHENRANGELOOSE] = '^\\\\s*(' . Exports::$src[XRANGEPLAINLOOSE] . ')' .\n                        '\\\\s+-\\\\s+' .\n                        '(' . Exports::$src[XRANGEPLAINLOOSE] . ')' .\n                        '\\\\s*$';\n\n// Star ranges basically just allow anything at all.\ndefine(__NAMESPACE__.'\\\\STAR', $R++);\nExports::$src[STAR] = '(<|>)?=?\\\\s*\\\\*';\n\nfor($i = 0; $i < $R; $i++) {\n    if(!isset(Exports::$re[$i]))\n        Exports::$re[$i] = new RegExp(Exports::$src[$i]);\n}\n\n/**\n *\n * @param JString $version\n * @param bool $loose\n * @return SemVer|null\n */\nfunction parse(JString $version, $loose = false)\n{\n    $r = $loose?Exports::$re[LOOSE]:Exports::$re[FULL];\n    /* @var $r \\vierbergenlars\\LibJs\\RexExp */\n    return ($r->test($version))? new SemVer($version, $loose):null;\n}\n\n/**\n * @param JString $version\n * @param bool $loose\n * @return JString|null\n */\nfunction valid(JString $version, $loose = false)\n{\n    $v = parse($version, $loose);\n    return $v?$v->version:null;\n}\n\n/**\n * @param JString $version\n * @param bool $loose\n * @return JString|null\n */\nfunction clean(JString $version, $loose = false)\n{\n    $s = parse($version, $loose);\n    return $s?$s->version:null;\n}\n\nclass SemVer extends JObject\n{\n    /**\n     * @var JString\n     */\n    public $version;\n\n    /**\n     * @var bool\n     */\n    public $loose;\n\n    /**\n     * @var JString\n     */\n    public $raw;\n\n    /**\n     *\n     * @var int\n     */\n    public $major;\n\n    /**\n     *\n     * @var int\n     */\n    public $minor;\n\n    /**\n     *\n     * @var int\n     */\n    public $patch;\n\n    /**\n     *\n     * @var JSArray\n     */\n    public $prerelease;\n\n    /**\n     *\n     * @var JSArray\n     */\n    public $build;\n\n    /**\n     * @param SemVer|JString|string $version\n     * @param bool $loose\n     */\n    public function __construct($version, $loose = false)\n    {\n        $this->loose = $loose;\n        if($version instanceof SemVer) {\n            $this->version = $version->version;\n            return;\n        }\n\n        $version = new JString($version);\n\n        $m = $version->trim()->match($loose?Exports::$re[LOOSE]:Exports::$re[FULL]);\n\n        if(!$m)\n            throw new \\RuntimeException('Invalid Version: '.$version);\n\n        $this->raw = $version;\n\n        // these are actually numbers\n        $this->major = (int)$m[1]->valueOf();\n        $this->minor = (int)$m[2]->valueOf();\n        $this->patch = (int)$m[3]->valueOf();\n\n        // numberify any prerelease numeric ids\n        if (!$m[4])\n            $this->prerelease = new JSArray();\n        else\n            $this->prerelease = $m[4]->split('.')->map(function($id) {\n                return (is_numeric($id->valueOf())) ? (int)$id->valueOf() : $id;\n            });\n\n        $this->build = $m[5]?$m[5]->split('.') : new JSArray();\n\n        $this->format();\n    }\n\n    public function format()\n    {\n       $this->version = new JString($this->major . '.' . $this->minor . '.' . $this->patch);\n        if ($this->prerelease->length)\n            $this->version = $this->version->concat('-', $this->prerelease->join('.'));\n        return $this->version;\n    }\n\n    public function inspect()\n    {\n        return '<SemVer \"'.$this.'\">';\n    }\n\n    public function __toString()\n    {\n        return $this->version->valueOf();\n    }\n\n    public function compare($other)\n    {\n        if(!$other instanceof SemVer)\n            $other = new SemVer($other, $this->loose);\n        return Util::JSor($this->compareMain($other),$this->comparePre($other));\n    }\n\n    public function compareMain($other)\n    {\n        if(!$other instanceof SemVer)\n            $other = new SemVer($other, $this->loose);\n        return Util::JSor(compareIdentifiers($this->major, $other->major),\n                compareIdentifiers($this->minor, $other->minor),\n                compareIdentifiers($this->patch, $other->patch));\n    }\n\n    public function comparePre($other)\n    {\n        if(!$other instanceof SemVer)\n            $other = new SemVer($other, $this->loose);\n\n        // NOT having a prerelease is > having one\n        if($this->prerelease->length && !$other->prerelease->length)\n            return -1;\n        else if(!$this->prerelease->length && $other->prerelease->length)\n            return 1;\n        else if(!$this->prerelease->length && !$other->prerelease->length)\n            return 0;\n\n        $i = 0;\n        do {\n            $a = $this->prerelease[$i];\n            if($a instanceof JString) $a = $a->valueOf();\n            $b = $other->prerelease[$i];\n            if($b instanceof JString) $b = $b->valueOf();\n\n            if ($a === null && $b === null)\n              return 0;\n            else if ($b === null)\n              return 1;\n            else if ($a === null)\n              return -1;\n            else if ($a === $b)\n              continue;\n            else\n              return compareIdentifiers($a, $b);\n        } while (++$i);\n    }\n\n    /**\n     * @param string $release\n     * @return SemVer\n     */\n    public function inc($release)\n    {\n        switch ($release) {\n            case 'major':\n                $this->major++;\n                $this->minor = -1;\n            case 'minor':\n                $this->minor++;\n                $this->patch = -1;\n            case 'patch':\n                $this->patch++;\n                $this->prerelease = new JSArray();\n                break;\n            case 'prerelease':\n                if ($this->prerelease->length === 0)\n                      $this->prerelease = new JSArray(array(0));\n                else {\n                    $i = $this->prerelease->length;\n                    while (--$i >= 0) {\n                        if (is_numeric($this->prerelease[$i])) {\n                            $this->prerelease[$i] = $this->prerelease[$i] + 1;\n                            $i = -2;\n                        }\n                    }\n                    if ($i === -1) // didn't increment anything\n                        $this->prerelease->push(0);\n                }\n                break;\n\n            default:\n                throw new \\LogicException('invalid increment argument: ' .$release);\n        }\n        $this->format();\n        return $this;\n    }\n}\n\nfunction inc($version, $release, $loose = false)\n{\n    try {\n        $s = new SemVer($version, $loose);\n        return (string)$s->inc($release)->version;\n    } catch(\\Exception $e) {\n        return null;\n    }\n}\n\nfunction compareIdentifiers($a, $b)\n{\n    $anum = is_numeric($a);\n    $bnum = is_numeric($b);\n\n    if($anum && $bnum) {\n        $a = (int)$a;\n        $b = (int)$b;\n    }\n\n    if($anum && !$bnum)\n        return -1;\n    elseif($bnum && !$anum)\n        return 1;\n    elseif($a < $b)\n        return -1;\n    elseif($a > $b)\n        return 1;\n    else\n        return 0;\n}\n\nfunction rcompareIdentifiers($a, $b)\n{\n    return compareIdentifiers($b, $a);\n}\n\nfunction compare($a, $b, $loose = false)\n{\n    $s = new SemVer($a, $loose);\n    return $s->compare($b);\n}\n\nfunction compareLoose($a, $b)\n{\n    return compare($a, $b, true);\n}\n\nfunction rcompare($a, $b, $loose = false)\n{\n    return compare($b, $a, $loose);\n}\n\nfunction semver_sort(JSArray $list, $loose = false)\n{\n    return $list->sort(function ($a, $b) use($loose) {\n        return compare($a, $b, $loose);\n    });\n}\n\nfunction semver_rsort(JSArray $list, $loose = false)\n{\n    return $list->sort(function($a, $b)use($loose) {\n        return rcompare($a, $b, $loose);\n    });\n}\n\nfunction gt($a, $b, $loose = false)\n{\n    return compare($a, $b, $loose) > 0;\n}\n\nfunction lt($a, $b, $loose = false)\n{\n    return compare($a, $b, $loose) < 0;\n}\n\nfunction eq($a, $b, $loose = false)\n{\n    return compare($a, $b, $loose) === 0;\n}\n\nfunction neq($a, $b, $loose = false)\n{\n    return compare($a, $b, $loose) !== 0;\n}\n\nfunction gte($a, $b, $loose = false)\n{\n    return compare($a, $b, $loose) >= 0;\n}\n\nfunction lte($a, $b, $loose = false)\n{\n    return compare($a, $b, $loose) <= 0;\n}\n\nfunction cmp($a, $op, $b, $loose = false)\n{\n    if($op instanceof JString)\n        $op = $op->valueOf();\n    switch ($op) {\n        case '===': $ret = $a === $b; break;\n        case '!==': $ret = $a !== $b; break;\n        case '': case '=': case '==': $ret = eq($a, $b, $loose); break;\n        case '!=': $ret = neq($a, $b, $loose); break;\n        case '>': $ret = gt($a, $b, $loose); break;\n        case '>=': $ret = gte($a, $b, $loose); break;\n        case '<': $ret = lt($a, $b, $loose); break;\n        case '<=': $ret = lte($a, $b, $loose); break;\n        default: throw new \\LogicException('Invalid operator: ' . $op);\n    }\n    return $ret;\n}\n\nclass Comparator extends JObject\n{\n    /**\n     * @var JString\n     */\n    public $value;\n\n    /**\n     * @var bool\n     */\n    public $loose;\n\n    /**\n     * @var SemVer|null\n     */\n    public $semver;\n\n    /**\n     * @var JString\n     */\n    public $operator;\n\n    public function __construct($comp, $loose = false)\n    {\n        $this->loose = $loose;\n        if($comp instanceof Comparator)\n            $comp = $comp->value;\n\n        $comp = new JString($comp);\n\n        $this->parse($comp);\n\n        if(!$this->semver instanceof SemVer)\n            $this->value = new JString('');\n        else\n            $this->value = new JString($this->operator.$this->semver->version);\n    }\n\n    public function parse(JString $comp)\n    {\n        $r = $this->loose?Exports::$re[COMPARATORLOOSE]:Exports::$re[COMPARATOR];\n        $m = $comp->match($r);\n\n        if(!$m)\n            throw new \\RuntimeException('Invalid comparator: '.$comp);\n\n        $this->operator = $m[1];\n        if(!$m[2])\n            $this->semver = null;\n        else {\n            $this->semver = new SemVer($m[2], $this->loose);\n\n            // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease)\n            // >=1.2.3 DOES NOT allow 1.2.3-beta\n            // <=1.2.3 DOES allow 1.2.3-beta\n            // However, <1.2.3 does NOT allow 1.2.3-beta,\n            // even though `1.2.3-beta < 1.2.3`\n            // The assumption is that the 1.2.3 version has something you\n            // *don't* want, so we push the prerelease down to the minimum.\n            if ($this->operator->valueOf() === '<' && !$this->semver->prerelease->length) {\n                $this->semver->prerelease = new JSArray(array(0));\n                $this->semver->format();\n            }\n        }\n    }\n\n    public function inspect()\n    {\n        return '<SemVer Comparator \"'.$this.'\">';\n    }\n\n    public function __toString()\n    {\n        return $this->value->valueOf();\n    }\n\n    public function test($version)\n    {\n        return ($this->semver == null) ? true:\n                cmp($version, $this->operator, $this->semver, $this->loose);\n    }\n}\n\nclass Range extends JObject\n{\n    /**\n     * @var bool\n     */\n    public $loose;\n\n    /**\n     * @var JString\n     */\n    public $raw;\n\n    /**\n     * @var JSArray\n     */\n    public $set;\n\n    /**\n     *\n     * @var JString\n     */\n    public $range;\n\n    public function __construct($range, $loose = false)\n    {\n        $this->loose = $loose;\n        if($range instanceof Range)\n            $range = $range->raw;\n\n        $range = new JString($range);\n\n        $this->raw = $range;\n\n        $that = $this;\n        // First, split based on boolean or ||\n        $this->set = $range->split(new RegExp('\\\\s*\\\\|\\\\|\\\\s*'))->map(function($range)use($that) {\n            return $that->parseRange($range->trim());\n        })->filter(function($c) {\n            return $c->length;\n        });\n\n        if(!$this->set->length) {\n            throw new \\RuntimeException('Invalid SemVer Range: ' . $range);\n        }\n\n        $this->format();\n    }\n\n    public function inspect()\n    {\n        return '<SemVer Range \"'.$this->raw.'\">';\n    }\n\n    public function format()\n    {\n        $this->range = $this->set->map(function($comps) {\n            return $comps->join(' ')->trim();\n        })->join('||')->trim();\n        return $this->range;\n    }\n\n    public function __toString()\n    {\n        return $this->range->valueOf();\n    }\n\n    public function parseRange(JString $range)\n    {\n        $loose = $this->loose;\n        $range = $range->trim();\n        // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`\n        $hr = $loose?Exports::$re[HYPHENRANGELOOSE]:Exports::$re[HYPHENRANGE];\n        $range = $range->replace($hr, function() {\n            return call_user_func_array(__NAMESPACE__.'\\\\hyphenReplace', func_get_args());\n        });\n\n        // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`\n        $range = $range->replace(Exports::$re[COMPARATORTRIM], comparatorTrimReplace);\n\n        // `~ 1.2.3` => `~1.2.3`\n        $range = $range->replace(Exports::$re[TILDETRIM], tildeTrimReplace);\n\n        // `^ 1.2.3` => `^1.2.3`\n        $range = $range->replace(Exports::$re[CARETTRIM], caretTrimReplace);\n\n        // normalize spaces\n        $range = $range->split(new RegExp('\\\\s+'))->join(' ');\n\n        // At this point, the range is completely trimmed and\n        // ready to be split into comparators.\n\n        $compRe = $loose ? Exports::$re[COMPARATORLOOSE] : Exports::$re[COMPARATOR];\n        $set = $range->split(' ')->map(function($comp) use($loose) {\n            return parseComparator($comp, $loose);\n        })->join(' ')->split(new RegExp('\\\\s+'));\n\n        if ($loose) {\n            // in loose mode, throw out any that are not valid comparators\n            $set = $set->filter(function($comp)use($compRe) {\n                return !!$comp->match($compRe);\n            });\n        }\n        $set = $set->map(function($comp) use($loose) {\n            return new Comparator($comp, $loose);\n        });\n\n\n        return $set;\n    }\n\n    // Placed after hyphenReplace in JS source\n    public function test($version)\n    {\n        if(!$version)\n            return false;\n        for($i = 0; $i < $this->set->length; $i++) {\n            if(testSet($this->set[$i], $version))\n                return true;\n        }\n        return false;\n    }\n}\n\nfunction toComparators($range, $loose = false)\n{\n    $r = new Range($range, $loose);\n    return $r->set->map(function($comp) {\n        return $comp->map(function($c) {\n            return $c->value;\n        })->join(' ')->trim()->split(' ');\n    });\n}\n\n// comprised of xranges, tildes, stars, and gtlt's at this point.\n// already replaced the hyphen ranges\n// turn into a set of JUST comparators.\nfunction parseComparator(JString $comp, $loose = false)\n{\n    $comp = replaceCarets($comp, $loose);\n    $comp = replaceTildes($comp, $loose);\n    $comp = replaceXRanges($comp, $loose);\n    $comp = replaceStars($comp, $loose);\n    return $comp;\n}\n\nfunction isX(JString $id = null)\n{\n    return !$id || $id->toLowerCase()->valueOf() === 'x' || $id->valueOf() === '*';\n}\n\n// ~, ~> --> * (any, kinda silly)\n// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0\n// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0\n// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0\n// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0\n// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0\nfunction replaceTildes(JString $comp, $loose = false) {\n    return $comp->trim()->split(new RegExp('\\\\s+'))->map(function($comp)use($loose) {\n        return replaceTilde($comp, $loose);\n    })->join(' ');\n}\n\nfunction replaceTilde(JString $comp, $loose = false) {\n  $r = $loose ? Exports::$re[TILDELOOSE] : Exports::$re[TILDE];\n  return $comp->replace($r, function(JString $_, JString $M = null, JString $m = null, JString $p = null, JString $pr = null) {\n    if (isX($M))\n      $ret = '';\n    else if (isX($m))\n      $ret = '>=' . $M . '.0.0-0 <' . ((int)(string)$M + 1) . '.0.0-0';\n    else if (isX($p))\n      // ~1.2 == >=1.2.0- <1.3.0-\n      $ret = '>=' . $M . '.' . $m . '.0-0 <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n    else if ($pr) {\n      if ($pr->charAt(0) !== '-')\n        $pr = '-' . $pr;\n      $ret = '>=' . $M . '.' . $m . '.' . $p . $pr .\n            ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n    } else\n      // ~1.2.3 == >=1.2.3-0 <1.3.0-0\n      $ret = '>=' . $M . '.' . $m . '.' . $p . '-0' .\n            ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n\n    return $ret;\n  });\n}\n\n// ^ --> * (any, kinda silly)\n// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0\n// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0\n// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0\n// ^1.2.3 --> >=1.2.3 <2.0.0\n// ^1.2.0 --> >=1.2.0 <2.0.0\nfunction replaceCarets(JString $comp, $loose = false) {\n  return $comp->trim()->split(new RegExp('\\\\s+'))->map(function($comp)use($loose) {\n    return replaceCaret($comp, $loose);\n  })->join(' ');\n}\n\nfunction replaceCaret(JString $comp, $loose = false) {\n  $r = $loose ? Exports::$re[CARETLOOSE] : Exports::$re[CARET];\n  return $comp->replace($r, function(JString $_, JString $M = null, JString $m = null, JString $p = null, JString $pr = null) {\n    if (isX($M))\n      $ret = '';\n    else if (isX($m))\n      $ret = '>=' . $M . '.0.0-0 <' . ((int)(string)$M + 1) . '.0.0-0';\n    else if (isX($p)) {\n      if ($M->valueOf() === '0')\n        $ret = '>=' . $M . '.' . $m . '.0-0 <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n      else\n        $ret = '>=' . $M . '.' . $m . '.0-0 <' . ((int)(string)$M + 1) . '.0.0-0';\n    } else if ($pr) {\n      if ($pr->charAt(0) !== '-')\n        $pr = '-' . $pr;\n      if ($M->valueOf() === '0') {\n        if ($m->valueOf() === '0')\n          $ret = '=' . $M . '.' . $m . '.' . $p . $pr;\n        else\n          $ret = '>=' . $M . '.' . $m . '.' . $p . $pr .\n                ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n      } else\n        $ret = '>=' . $M . '.' . $m . '.' . $p . $pr .\n              ' <' . ((int)(string)$M + 1) . '.0.0-0';\n    } else {\n      if ($M->valueOf() === '0') {\n        if ($m->valueOf() === '0')\n          $ret = '=' . $M . '.' . $m . '.' . $p;\n        else\n          $ret = '>=' . $M . '.' . $m . '.' . $p . '-0' .\n                ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n      } else\n        $ret = '>=' . $M . '.' . $m . '.' . $p . '-0' .\n              ' <' . ((int)(string)$M + 1) . '.0.0-0';\n    }\n\n    return $ret;\n  });\n}\n\nfunction replaceXRanges(JString $comp, $loose = false) {\n  return $comp->split(new RegExp('\\\\s+'))->map(function($comp)use($loose) {\n    return replaceXRange($comp, $loose);\n  })->join(' ');\n}\n\nfunction replaceXRange(JString $comp, $loose = false) {\n  $comp = $comp->trim();\n  $r = $loose ? Exports::$re[XRANGELOOSE] : Exports::$re[XRANGE];\n  return $comp->replace($r, function(JString $ret, JString $gtlt, JString $M = null, JString $m = null, JString $p = null, JString $pr=null) {\n    $xM = isX($M);\n    $xm = $xM || isX($m);\n    $xp = $xm || isX($p);\n    $anyX = $xp;\n    $gtlt = (string)$gtlt;\n\n    if ($gtlt === '=' && $anyX)\n      $gtlt = '';\n\n    if ($gtlt && $anyX) {\n      // replace X with 0, and then append the -0 min-prerelease\n      if ($xM)\n        $M = 0;\n      if ($xm)\n        $m = 0;\n      if ($xp)\n        $p = 0;\n\n      if ($gtlt === '>') {\n        // >1 => >=2.0.0-0\n        // >1.2 => >=1.3.0-0\n        // >1.2.3 => >= 1.2.4-0\n        $gtlt = '>=';\n        if ($xM) {\n          // no change\n        } else if ($xm) {\n          $M = (int)(string)$M + 1;\n          $m = 0;\n          $p = 0;\n        } else if ($xp) {\n          $m = (int)(string)$m + 1;\n          $p = 0;\n        }\n      }\n\n\n      $ret = $gtlt . $M . '.' . $m . '.' . $p . '-0';\n    } else if ($xM) {\n      // allow any\n      $ret = '*';\n    } else if ($xm) {\n      // append '-0' onto the version, otherwise\n      // '1.x.x' matches '2.0.0-beta', since the tag\n      // *lowers* the version value\n      $ret = '>=' . $M . '.0.0-0 <' . ((int)(string)$M + 1) . '.0.0-0';\n    } else if ($xp) {\n      $ret = '>=' . $M . '.' . $m . '.0-0 <' . $M . '.' . ((int)(string)$m + 1) . '.0-0';\n    }\n\n    return $ret;\n  });\n}\n\n// Because * is AND-ed with everything else in the comparator,\n// and '' means \"any version\", just remove the *s entirely.\nfunction replaceStars(JString $comp, $loose = false) {\n  // Looseness is ignored here.  star is always as loose as it gets!\n  return $comp->trim()->replace(Exports::$re[STAR], '');\n}\n\n// This function is passed to string.replace(re[HYPHENRANGE])\n// M, m, patch, prerelease, build\n// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5\n// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do\n// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0\nfunction hyphenReplace(JString $_,\n                       JString $from = null, JString $fM = null, JString $fm = null, JString $fp = null, JString $fpr = null, JString $fb = null,\n                       JString $to = null, JString $tM = null, JString $tm = null, JString $tp = null, JString $tpr = null, JString $tb = null) {\n\n  if (isX($fM))\n    $from = '';\n  else if (isX($fm))\n    $from = '>=' . $fM . '.0.0-0';\n  else if (isX($fp))\n    $from = '>=' . $fM . '.' . $fm . '.0-0';\n  else\n    $from = '>=' . $from;\n\n  if (isX($tM))\n    $to = '';\n  else if (isX($tm))\n    $to = '<' . ((int)(string)$tM + 1) . '.0.0-0';\n  else if (isX($tp))\n    $to = '<' . $tM . '.' . ((int)(string)$tm + 1) . '.0-0';\n  else if ($tpr)\n    $to = '<=' . $tM . '.' . $tm . '.' . $tp . '-' . $tpr;\n  else\n    $to = '<=' . $to;\n\n  $s = new JString($from.' '.$to);\n  return $s->trim();\n}\n\n// Range.prototype.test is moved to the Range object in PHP\n\nfunction testSet(JSArray $set, $version) {\n  for ($i = 0; $i < $set->length; $i++) {\n    if (!$set[$i]->test($version))\n      return false;\n  }\n  return true;\n}\n\nfunction satisfies($version, $range, $loose = false)\n{\n    try {\n        $range = new Range($range, $loose);\n    } catch(\\Exception $e) {\n        return false;\n    }\n    return $range->test($version);\n}\n\nfunction maxSatisfying(JSArray $versions, $range, $loose = false)\n{\n  return $versions->filter(function($version)use($range, $loose) {\n    return satisfies($version, $range, $loose);\n  })->sort(function($a, $b)use($loose) {\n    return rcompare($a, $b, $loose);\n  })->offsetGet(0);\n}\n\nfunction validRange($range, $loose = false) {\n  try {\n    // Return '*' instead of '' so that truthiness works.\n    // This will throw if it's invalid anyway\n    $r = new Range($range, $loose);\n    return (string)Util::JSor($r->range, new JString('*'));\n  } catch (\\Exception $e) {\n    return null;\n  }\n}\n\n// Determine if version is less than all the versions possible in the range\nfunction ltr($version, $range, $loose = false)\n{\n    return outside($version, $range, '<', $loose);\n}\n\n// Determine if version is greater than all the versions possible in the range.\nfunction gtr($version, $range, $loose = false)\n{\n    return outside($version, $range, '>', $loose);\n}\n\nfunction outside($version, $range, $hilo, $loose = false)\n{\n    $version = new SemVer($version, $loose);\n    $range = new Range($range, $loose);\n\n    switch($hilo) {\n        case '>':\n            $gtfn = __NAMESPACE__.'\\\\gt';\n            $ltefn = __NAMESPACE__.'\\\\lte';\n            $ltfn = __NAMESPACE__.'\\\\lt';\n            $comp = '>';\n            $ecomp = '>=';\n            break;\n        case '<':\n            $gtfn = __NAMESPACE__.'\\\\lt';\n            $ltefn = __NAMESPACE__.'\\\\gte';\n            $ltfn = __NAMESPACE__.'\\\\gt';\n            $comp = '<';\n            $ecomp = '<=';\n            break;\n        default:\n            throw new \\LogicException('Must provide a hilo val of \"<\" or \">\"');\n      }\n\n    // If it satisifes the range it is not outside\n    if (satisfies($version, $range, $loose)) {\n      return false;\n    }\n\n    // From now on, variable terms are as if we're in \"gtr\" mode.\n    // but note that everything is flipped for the \"ltr\" function.\n\n    for ($i = 0; $i < $range->set->length; ++$i) {\n        $comparators = $range->set[$i];\n\n        $high = null;\n        $low = null;\n\n        $comparators->JSforEach(function($comparator)use($loose,&$high,&$low) {\n            $high = Util::JSor($high, $comparator);\n            $low = Util::JSor($low, $comparator);\n            if (gtfn($comparator->semver, $high->semver, $loose)) {\n                $high = $comparator;\n            } else if (ltfn($comparator->semver, $low->semver, $loose)) {\n                $low = $comparator;\n            }\n        });\n\n        // If the edge version comparator has a operator then our version\n        // isn't outside it\n        if ($high->operator->valueOf() === $comp || $high->operator->valueOf() === $ecomp) {\n            return false;\n        }\n\n        // If the lowest version comparator has an operator and our version\n        // is less than it then it isn't higher than the range\n        if ((!$low->operator->valueOf() || $low->operator->valueOf() === $comp) &&\n            ltefn($version, $low->semver)) {\n            return false;\n        } else if ($low->operator->valueOf() === $ecomp && ltfn($version, $low->semver)) {\n            return false;\n        }\n    }\n    return true;\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/version.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer;\n\nuse vierbergenlars\\SemVer\\Internal\\SemVer;\nuse vierbergenlars\\SemVer\\Internal\\G;\n\nclass version\n{\n    /**\n     *\n     * @var SemVer\n     */\n    private $version;\n\n    /**\n     * Initializes the version object with a simple version\n     * @param  string          $version A simple, single version string\n     * @param  bool            $loose\n     * @throws SemVerException\n     */\n    public function __construct($version, $loose = false)\n    {\n        try {\n            $this->version = new SemVer($version, $loose);\n        } catch(\\RuntimeException $ex) {\n            throw new SemVerException($ex->getMessage(), $version);\n        }\n    }\n\n    /**\n     * Get the full version\n     * @return string\n     */\n    public function getVersion()\n    {\n        return (string) $this->version;\n    }\n\n    /**\n     * Get the major version number\n     * @return int\n     */\n    public function getMajor()\n    {\n        return (int) $this->version->major;\n    }\n\n    /**\n     * Get the minor version number\n     * @return int\n     */\n    public function getMinor()\n    {\n        return (int) $this->version->minor;\n    }\n\n    /**\n     * Get the patch version number\n     * @return int\n     */\n    public function getPatch()\n    {\n        return (int) $this->version->patch;\n    }\n\n    /**\n     * Get the build number\n     * @return array\n     */\n    public function getBuild()\n    {\n        return (array) $this->version->build->valueOf();\n    }\n\n    /**\n     * Get the prerelease appended to the version\n     * @return array\n     */\n    public function getPrerelease()\n    {\n        return (array) $this->version->prerelease->valueOf();\n    }\n\n    /**\n     * Returns a valid version\n     * @return string\n     * @see self::getVersion()\n     */\n    public function valid()\n    {\n        return $this->getVersion();\n    }\n\n    /**\n     * Increment the version number\n     * @param  string                         $what One of 'major', 'minor', 'patch' or 'prerelease'\n     * @return \\vierbergenlars\\SemVer\\version\n     * @throws LogicException                When an invalid increment value is given\n     */\n    public function inc($what)\n    {\n        $this->version->inc($what);\n        return $this;\n    }\n\n    /**\n     * Checks whether this version satisfies an expression\n     * @param  expression $versions The expression to check against\n     * @return bool\n     */\n    public function satisfies(expression $versions)\n    {\n        return $versions->satisfiedBy($this);\n    }\n\n    public function __toString()\n    {\n        return $this->getVersion();\n    }\n\n    /**\n     * Compare two versions\n     * @param  string                   $v1  The first version\n     * @param  string                   $cmp The comparator, one of '==', '!=', '>', '>=', '<', '<=', '===', '!=='\n     * @param  string                   $v2  The second version\n     * @param  bool                     $loose\n     * @return bool\n     * @throws LogicException\n     */\n    public static function cmp($v1, $cmp, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        try {\n            return G::cmp($v1, $cmp, $v2, $loose);\n        } catch(\\LogicException $e) {\n            throw new \\UnexpectedValueException($e->getMessage(), $e->getCode(), $e);\n        }\n    }\n\n    /**\n     * Checks ifa given string is greater than another\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return boolean\n     */\n    public static function gt($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::gt($v1, $v2, $loose);\n    }\n\n    /**\n     * Checks ifa given string is greater than, or equal to another\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return boolean\n     */\n    public static function gte($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::gte($v1, $v2, $loose);\n    }\n\n    /**\n     * Checks ifa given string is less than another\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return boolean\n     */\n    public static function lt($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::lt($v1, $v2, $loose);\n    }\n\n    /**\n     * Checks ifa given string is less than, or equal to another\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return boolean\n     */\n    public static function lte($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::lte($v1, $v2, $loose);\n    }\n\n    /**\n     * Checks ifa given string is equal to another\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return boolean\n     */\n    public static function eq($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::eq($v1, $v2, $loose);\n    }\n\n    /**\n     * Checks ifa given string is not equal to another\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return boolean\n     */\n    public static function neq($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::neq($v1, $v2, $loose);\n    }\n\n    /**\n     * Compares two versions, can be used with usort()\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return int            0 when they are equal, -1 ifthe second version is smaller, 1 ifthe second version is greater\n     */\n    public static function compare($v1, $v2, $loose = false)\n    {\n        if($v1 instanceof self)\n            $v1 = $v1->getVersion();\n        if($v2 instanceof self)\n            $v2 = $v2->getVersion();\n        return G::compare($v1, $v2, $loose);\n    }\n\n    /**\n     * Reverse compares two versions, can be used with usort()\n     * @param  string|version $v1 The first version\n     * @param  string|version $v2 The second version\n     * @param  bool           $loose\n     * @return int            0 when they are equal, 1 ifthe second version is smaller, -1 ifthe second version is greater\n     */\n    public static function rcompare($v1, $v2, $loose = false)\n    {\n        return self::compare($v2, $v1, $loose);\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/tests/RegressionTest.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer\\Tests;\n\nuse vierbergenlars\\SemVer;\n\nclass RegressionTest extends \\PHPUnit_Framework_TestCase\n{\n    public function testBug23()\n    {\n        $this->assertTrue(SemVer\\version::lt('3.0.0', '4.0.0-beta.1'), '3.0.0 < 4.0.0-beta.1 (Bug #23)');\n    }\n\n    public function testBug24()\n    {\n        $this->assertFalse(SemVer\\version::gt('4.0.0-beta.9', '4.0.0-beta.10'),\n            '4.0.0-beta.9 < 4.0.0-beta.10 (Bug #24)');\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/tests/SemVerTest.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer\\Tests\\Internal;\n\nuse vierbergenlars\\SemVer\\Internal as SemVer;\n\nclass SemVerTest extends \\PHPUnit_Framework_TestCase\n{\n    public function testComparison()\n    {\n        $compare = array(\n            array(\"0.0.0\", \"0.0.0-foo\"),\n            array(\"0.0.1\", \"0.0.0\"),\n            array(\"1.0.0\", \"0.9.9\"),\n            array(\"0.10.0\", \"0.9.0\"),\n            array(\"0.99.0\", \"0.10.0\"),\n            array(\"2.0.0\", \"1.2.3\"),\n            array(\"v0.0.0\", \"0.0.0-foo\", true),\n            array(\"v0.0.1\", \"0.0.0\", true),\n            array(\"v1.0.0\", \"0.9.9\", true),\n            array(\"v0.10.0\", \"0.9.0\", true),\n            array(\"v0.99.0\", \"0.10.0\", true),\n            array(\"v2.0.0\", \"1.2.3\", true),\n            array(\"0.0.0\", \"v0.0.0-foo\", true),\n            array(\"0.0.1\", \"v0.0.0\", true),\n            array(\"1.0.0\", \"v0.9.9\", true),\n            array(\"0.10.0\", \"v0.9.0\", true),\n            array(\"0.99.0\", \"v0.10.0\", true),\n            array(\"2.0.0\", \"v1.2.3\", true),\n            array(\"1.2.3\", \"1.2.3-asdf\"),\n            array(\"1.2.3\", \"1.2.3-4\"),\n            array(\"1.2.3\", \"1.2.3-4-foo\"),\n            array(\"1.2.3-5-foo\", \"1.2.3-5\"),\n            array(\"1.2.3-5\", \"1.2.3-4\"),\n            array(\"1.2.3-5-foo\", \"1.2.3-5-Foo\"),\n            //array('1.2.3-0','1.2.3'),\n            array('3.0.0', '2.7.2+asdf'),\n            array('1.2.3-a.10', '1.2.3-a.5'),\n            array('1.2.3-a.b', '1.2.3-a.5'),\n            array('1.2.3-a.b', '1.2.3-a'),\n            array('1.2.3-a.b.c.10.d.5', '1.2.3-a.b.c.5.d.100')\n        );\n        foreach ($compare as $set) {\n            $a = $set[0];\n            $b = $set[1];\n            $loose = isset($set[2]) && $set[2];\n            $this->assertTrue(SemVer\\G::gt($a, $b, $loose), \"%s > gt('\" . $a . \"', '\" . $b . \"')\");\n            $this->assertTrue(SemVer\\G::lt($b, $a, $loose), \"%s > lt('\" . $b . \"', '\" . $a . \"')\");\n            $this->assertFalse(SemVer\\G::gt($b, $a, $loose), \"%s > !gt('\" . $b . \"', '\" . $a . \"')\");\n            $this->assertFalse(SemVer\\G::lt($a, $b, $loose), \"%s > !lt('\" . $a . \"', '\" . $b . \"')\");\n            $this->assertTrue(SemVer\\G::eq($a, $a, $loose), \"%s > eq('\" . $a . \"', '\" . $a . \"')\");\n            $this->assertTrue(SemVer\\G::eq($b, $b, $loose), \"%s > eq('\" . $b . \"', '\" . $b . \"')\");\n            $this->assertTrue(SemVer\\G::neq($a, $b, $loose), \"%s > neq('\" . $a . \"', '\" . $b . \"')\");\n            $this->assertTrue(SemVer\\G::cmp($b, \"==\", $b, $loose), \"%s > cmp('\" . $b . \"' == '\" . $b . \"')\");\n            $this->assertTrue(SemVer\\G::cmp($a, \">=\", $b, $loose), \"%s > cmp('\" . $a . \"' >= '\" . $b . \"')\");\n            $this->assertTrue(SemVer\\G::cmp($b, \"<=\", $a, $loose), \"%s > cmp('\" . $b . \"' <= '\" . $a . \"')\");\n            $this->assertTrue(SemVer\\G::cmp($a, \"!=\", $b, $loose), \"%s > cmp('\" . $a . \"' != '\" . $b . \"')\");\n        }\n    }\n\n    public function testEquality()\n    {\n        $compare = array(\n            array(\"1.2.3\", \"v1.2.3\", true),\n            array(\"1.2.3\", \"=1.2.3\", true),\n            array(\"1.2.3\", \"v 1.2.3\", true),\n            array(\"1.2.3\", \"= 1.2.3\", true),\n            array(\"1.2.3\", \" v1.2.3\", true),\n            array(\"1.2.3\", \" =1.2.3\", true),\n            array(\"1.2.3\", \" v 1.2.3\", true),\n            array(\"1.2.3\", \" = 1.2.3\", true),\n            array(\"1.2.3-0\", \"v1.2.3-0\", true),\n            array(\"1.2.3-0\", \"=1.2.3-0\", true),\n            array(\"1.2.3-0\", \"v 1.2.3-0\", true),\n            array(\"1.2.3-0\", \"= 1.2.3-0\", true),\n            array(\"1.2.3-0\", \" v1.2.3-0\", true),\n            array(\"1.2.3-0\", \" =1.2.3-0\", true),\n            array(\"1.2.3-0\", \" v 1.2.3-0\", true),\n            array(\"1.2.3-0\", \" = 1.2.3-0\", true),\n            array(\"1.2.3-01\", \"v1.2.3-1\", true),\n            array(\"1.2.3-01\", \"=1.2.3-1\", true),\n            array(\"1.2.3-01\", \"v 1.2.3-1\", true),\n            array(\"1.2.3-01\", \"= 1.2.3-1\", true),\n            array(\"1.2.3-01\", \" v1.2.3-1\", true),\n            array(\"1.2.3-01\", \" =1.2.3-1\", true),\n            array(\"1.2.3-01\", \" v 1.2.3-1\", true),\n            array(\"1.2.3-01\", \" = 1.2.3-1\", true),\n            array(\"1.2.3-beta\", \"v1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \"=1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \"v 1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \"= 1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \" v1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \" =1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \" v 1.2.3-beta\", true),\n            array(\"1.2.3-beta\", \" = 1.2.3-beta\", true),\n            array(\"1.2.3-beta+build\", \" = 1.2.3-beta+otherbuild\", true),\n            array(\"1.2.3+build\", \" = 1.2.3+otherbuild\", true),\n            array(\"1.2.3-beta+build\", \"1.2.3-beta+otherbuild\", true),\n            array(\"1.2.3+build\", \"1.2.3+otherbuild\"),\n            array(\"1.2.3+build\", '1.2.3+otherbuild'),\n            array(\"  v1.2.3+build\", \"1.2.3+otherbuild\")\n\n        );\n        foreach ($compare as $set) {\n            $a = $set[0];\n            $b = $set[1];\n            $loose = isset($set[2]) && $set[2];\n            try {\n                $this->assertTrue(SemVer\\G::eq($a, $b, $loose), \"%s > eq('\" . $a . \"', '\" . $b . \"')\");\n                $this->assertFalse(SemVer\\G::neq($a, $b, $loose), \"%s > !neq('\" . $a . \"', '\" . $b . \"')\");\n                $this->assertTrue(SemVer\\G::cmp($a, \"==\", $b, $loose), \"%s > cmp(\" . $a . \"==\" . $b . \")\");\n                $this->assertFalse(SemVer\\G::cmp($a, \"!=\", $b, $loose), \"%s > !cmp(\" . $a . \"!=\" . $b . \")\");\n                $this->assertFalse(SemVer\\G::cmp($a, \"===\", $b, $loose), \"%s > !cmp(\" . $a . \"===\" . $b . \")\");\n                $this->assertTrue(SemVer\\G::cmp($a, \"!==\", $b, $loose), \"%s > cmp(\" . $a . \"!==\" . $b . \")\");\n                $this->assertFalse(SemVer\\G::gt($a, $b, $loose), \"%s > !gt('\" . $a . \"', '\" . $b . \"')\");\n                $this->assertTrue(SemVer\\G::gte($a, $b, $loose), \"%s > gte('\" . $a . \"', '\" . $b . \"')\");\n                $this->assertFalse(SemVer\\G::lt($a, $b, $loose), \"%s > !lt('\" . $a . \"', '\" . $b . \"')\");\n                $this->assertTrue(SemVer\\G::lte($a, $b, $loose), \"%s > lte('\" . $a . \"', '\" . $b . \"')\");\n            } catch (\\Exception $e) {\n                $this->fail(\"Exception while comparing $set[0] and $set[1]\");\n            }\n        }\n    }\n\n    public function testRange()\n    {\n        $compare = array(\n            array(\"1.0.0 - 2.0.0\", \"1.2.3\"),\n            array(\"1.0.0\", \"1.0.0\"),\n            array(\">=*\", \"0.2.4\"),\n            array(\"\", \"1.0.0\"),\n            array(\"*\", \"1.2.3\"),\n            array('*', 'v1.2.3-foo', true),\n            array(\">=1.0.0\", \"1.0.0\"),\n            array(\">=1.0.0\", \"1.0.1\"),\n            array(\">=1.0.0\", \"1.1.0\"),\n            array(\">1.0.0\", \"1.0.1\"),\n            array(\">1.0.0\", \"1.1.0\"),\n            array(\"<=2.0.0\", \"2.0.0\"),\n            array(\"<=2.0.0\", \"1.9999.9999\"),\n            array(\"<=2.0.0\", \"0.2.9\"),\n            array(\"<2.0.0\", \"1.9999.9999\"),\n            array(\"<2.0.0\", \"0.2.9\"),\n            array(\">= 1.0.0\", \"1.0.0\"),\n            array(\">=  1.0.0\", \"1.0.1\"),\n            array(\">=   1.0.0\", \"1.1.0\"),\n            array(\"> 1.0.0\", \"1.0.1\"),\n            array(\">  1.0.0\", \"1.1.0\"),\n            array(\"<=   2.0.0\", \"2.0.0\"),\n            array(\"<= 2.0.0\", \"1.9999.9999\"),\n            array(\"<=  2.0.0\", \"0.2.9\"),\n            array(\"<    2.0.0\", \"1.9999.9999\"),\n            array(\"<\\t2.0.0\", \"0.2.9\"),\n            array(\">=0.1.97\", \"v0.1.97\", true),\n            array(\">=0.1.97\", \"0.1.97\"),\n            array(\"0.1.20 || 1.2.4\", \"1.2.4\"),\n            array(\">=0.2.3 || <0.0.1\", \"0.0.0\"),\n            array(\">=0.2.3 || <0.0.1\", \"0.2.3\"),\n            array(\">=0.2.3 || <0.0.1\", \"0.2.4\"),\n            array(\"||\", \"1.3.4\"),\n            array(\"2.x.x\", \"2.1.3\"),\n            array(\"1.2.x\", \"1.2.3\"),\n            array(\"1.2.x || 2.x\", \"2.1.3\"),\n            array(\"1.2.x || 2.x\", \"1.2.3\"),\n            array(\"x\", \"1.2.3\"),\n            array(\"2.*.*\", \"2.1.3\"),\n            array(\"1.2.*\", \"1.2.3\"),\n            array(\"1.2.* || 2.*\", \"2.1.3\"),\n            array(\"1.2.* || 2.*\", \"1.2.3\"),\n            array(\"*\", \"1.2.3\"),\n            array(\"2\", \"2.1.2\"),\n            array(\"2.3\", \"2.3.1\"),\n            array(\"~2.4\", \"2.4.0\"), // >=2.4.0 <2.5.0\n            array(\"~2.4\", \"2.4.5\"),\n            array(\"~>3.2.1\", \"3.2.2\"), // >=3.2.1 <3.3.0\n            array(\"~1\", \"1.2.3\"), // >=1.0.0 <2.0.0\n            array(\"~>1\", \"1.2.3\"),\n            array(\"~> 1\", \"1.2.3\"),\n            array(\"~1.0\", \"1.0.2\"), // >=1.0.0 <1.1.0\n            array(\"~ 1.0\", \"1.0.2\"),\n            array(\"~1.0.3\", \"1.0.12\"),\n            array(\">=1\", \"1.0.0\"),\n            array(\">= 1\", \"1.0.0\"),\n            array(\"<1.2\", \"1.1.1\"),\n            array(\"< 1.2\", \"1.1.1\"),\n            array(\"1\", \"1.0.0beta\", true),\n            array(\"~v0.5.4-pre\", \"0.5.5\"),\n            array(\"~v0.5.4-pre\", \"0.5.4\"),\n            array('=0.7.x', '0.7.2'),\n            array('>=0.7.x', '0.7.2'),\n            array('=0.7.x', '0.7.0-asdf'),\n            array('>=0.7.x', '0.7.0-asdf'),\n            array('<=0.7.x', '0.6.2'),\n            array('~1.2.1 >=1.2.3', '1.2.3'),\n            array('~1.2.1 =1.2.3', '1.2.3'),\n            array('~1.2.1 1.2.3', '1.2.3'),\n            array('~1.2.1 >=1.2.3 1.2.3', '1.2.3'),\n            array('~1.2.1 1.2.3 >=1.2.3', '1.2.3'),\n            array('~1.2.1 1.2.3', '1.2.3'),\n            array('>=1.2.1 1.2.3', '1.2.3'),\n            array('1.2.3 >=1.2.1', '1.2.3'),\n            array('>=1.2.3 >=1.2.1', '1.2.3'),\n            array('>=1.2.1 >=1.2.3', '1.2.3'),\n            array('<=1.2.3', '1.2.3-beta'),\n            array('>1.2', '1.3.0-beta'),\n            array('>=1.2', '1.2.8'),\n            array('^1.2.3', '1.8.1'),\n            array('^1.2.3', '1.2.3-beta'),\n            array('^0.1.2', '0.1.2'),\n            array('^0.1', '0.1.2'),\n            array('^1.2', '1.4.2'),\n            array('^1.2 ^1', '1.4.2'),\n            array('^1.2', '1.2.0-pre'),\n            array('^1.2.3', '1.2.3-pre')\n        );\n        foreach ($compare as $set) {\n            $loose = isset($set[2]) && $set[2];\n\n            $this->assertTrue(SemVer\\G::satisfies($set[1], $set[0], $loose),\n                \"%s > $set[0] should be satisfied by $set[1]\");\n        }\n    }\n\n    public function testNegativeRange()\n    {\n        $compare = array(\n            array(\"1.0.0 - 2.0.0\", \"2.2.3\"),\n            array(\"1.0.0\", \"1.0.1\"),\n            array(\">=1.0.0\", \"0.0.0\"),\n            array(\">=1.0.0\", \"0.0.1\"),\n            array(\">=1.0.0\", \"0.1.0\"),\n            array(\">1.0.0\", \"0.0.1\"),\n            array(\">1.0.0\", \"0.1.0\"),\n            array(\"<=2.0.0\", \"3.0.0\"),\n            array(\"<=2.0.0\", \"2.9999.9999\"),\n            array(\"<=2.0.0\", \"2.2.9\"),\n            array(\"<2.0.0\", \"2.9999.9999\"),\n            array(\"<2.0.0\", \"2.2.9\"),\n            array(\">=0.1.97\", \"v0.1.93\", true),\n            array(\">=0.1.97\", \"0.1.93\"),\n            array(\"0.1.20 || 1.2.4\", \"1.2.3\"),\n            array(\">=0.2.3 || <0.0.1\", \"0.0.3\"),\n            array(\">=0.2.3 || <0.0.1\", \"0.2.2\"),\n            array(\"2.x.x\", \"1.1.3\"),\n            array(\"2.x.x\", \"3.1.3\"),\n            array(\"1.2.x\", \"1.3.3\"),\n            array(\"1.2.x || 2.x\", \"3.1.3\"),\n            array(\"1.2.x || 2.x\", \"1.1.3\"),\n            array(\"2.*.*\", \"1.1.3\"),\n            array(\"2.*.*\", \"3.1.3\"),\n            array(\"1.2.*\", \"1.3.3\"),\n            array(\"1.2.* || 2.*\", \"3.1.3\"),\n            array(\"1.2.* || 2.*\", \"1.1.3\"),\n            array(\"2\", \"1.1.2\"),\n            array(\"2.3\", \"2.4.1\"),\n            array(\"~2.4\", \"2.5.0\"), // >=2.4.0 <2.5.0\n            array(\"~2.4\", \"2.3.9\"),\n            array(\"~>3.2.1\", \"3.3.2\"), // >=3.2.1 <3.3.0\n            array(\"~>3.2.1\", \"3.2.0\"), // >=3.2.1 <3.3.0\n            array(\"~1\", \"0.2.3\"), // >=1.0.0 <2.0.0\n            array(\"~>1\", \"2.2.3\"),\n            array(\"~1.0\", \"1.1.0\"), // >=1.0.0 <1.1.0\n            array(\"<1\", \"1.0.0\"),\n            array(\">=1.2\", \"1.1.1\"),\n            array(\"1\", \"2.0.0beta\", true),\n            array(\"~v0.5.4-beta\", \"0.5.4-alpha\"),\n            array('<1', '1.0.0beta', true),\n            array('< 1', '1.0.0beta', true),\n            array('=0.7.x', '0.8.2'),\n            array('>=0.7.x', '0.6.2'),\n            array('<=0.7.x', '0.7.2'),\n            array('<1.2.3', '1.2.3-beta'),\n            array('=1.2.3', '1.2.3-beta'),\n            array('>1.2', '1.2.8'),\n            array('^1.2.3', '2.0.0-alpha'),\n            array('^1.2.3', '1.2.2'),\n            array('^1.2', '1.1.9'),\n            // Invalid ranges are never satisfied\n            array('blerg', '1.2.3'),\n            array('git+https://user:password0123@github.com/foo', '123.0.0', true),\n            array('^1.2.3', '2.0.0-pre')\n        );\n        foreach ($compare as $set) {\n            $loose = isset($set[2]) && $set[2];\n            $this->assertFalse(SemVer\\G::satisfies($set[1], $set[0], $loose),\n                \"%s > $set[0] should not be satisfied by $set[1]\");\n        }\n    }\n\n    public function testIncrementVersions()\n    {\n        $compare = array(\n            array(\"1.2.3\", \"major\", \"2.0.0\"),\n            array(\"1.2.3\", \"minor\", \"1.3.0\"),\n            array(\"1.2.3\", \"patch\", \"1.2.4\"),\n            array(\"1.2.3tag\", \"major\", \"2.0.0\", true),\n            array(\"1.2.3-tag\", \"major\", \"2.0.0\"),\n            array(\"1.2.3\", \"fake\", null),\n            array(\"fake\", \"major\", null),\n            array(\"1.2.3\", \"prerelease\", \"1.2.3-0\"),\n            array(\"1.2.3-0\", \"prerelease\", \"1.2.3-1\"),\n            array(\"1.2.3-alpha.0.beta\", \"prerelease\", \"1.2.3-alpha.1.beta\"),\n            array(\"1.2.3-alpha.1.beta\", \"prerelease\", \"1.2.3-alpha.2.beta\"),\n            array(\"1.2.3-alpha.2.beta\", \"prerelease\", \"1.2.3-alpha.3.beta\"),\n            array(\"1.2.3-alpha.10.0.beta\", \"prerelease\", \"1.2.3-alpha.10.1.beta\"),\n            array(\"1.2.3-alpha.10.1.beta\", \"prerelease\", \"1.2.3-alpha.10.2.beta\"),\n            array(\"1.2.3-alpha.10.2.beta\", \"prerelease\", \"1.2.3-alpha.10.3.beta\"),\n            array(\"1.2.3-alpha.10.beta.0\", \"prerelease\", \"1.2.3-alpha.10.beta.1\"),\n            array(\"1.2.3-alpha.10.beta.1\", \"prerelease\", \"1.2.3-alpha.10.beta.2\"),\n            array(\"1.2.3-alpha.10.beta.2\", \"prerelease\", \"1.2.3-alpha.10.beta.3\"),\n            array(\"1.2.3-alpha.9.beta\", \"prerelease\", \"1.2.3-alpha.10.beta\"),\n            array(\"1.2.3-alpha.10.beta\", \"prerelease\", \"1.2.3-alpha.11.beta\"),\n            array(\"1.2.3-alpha.12.beta\", \"prerelease\", \"1.2.3-alpha.13.beta\")\n        );\n        foreach ($compare as $set) {\n            $s = $set[0];\n            $loose = isset($set[3]) && $set[3];\n\n            $found = SemVer\\G::inc($set[0], $set[1], $loose);\n            $this->assertEquals($found, $set[2]);\n        }\n    }\n\n    public function testValidRange()\n    {\n        $compare = array(\n            array(\"1.0.0 - 2.0.0\", \">=1.0.0 <=2.0.0\"),\n            array(\"1.0.0\", \"1.0.0\"),\n            array(\">=*\", \">=0.0.0-0\"),\n            array(\"\", \"*\"),\n            array(\"*\", \"*\"),\n            array(\">=1.0.0\", \">=1.0.0\"),\n            array(\">1.0.0\", \">1.0.0\"),\n            array(\"<=2.0.0\", \"<=2.0.0\"),\n            array(\"1\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\"<=2.0.0\", \"<=2.0.0\"),\n            array(\"<2.0.0\", \"<2.0.0-0\"),\n            array(\">= 1.0.0\", \">=1.0.0\"),\n            array(\">=  1.0.0\", \">=1.0.0\"),\n            array(\">=   1.0.0\", \">=1.0.0\"),\n            array(\"> 1.0.0\", \">1.0.0\"),\n            array(\">  1.0.0\", \">1.0.0\"),\n            array(\"<=   2.0.0\", \"<=2.0.0\"),\n            array(\"<= 2.0.0\", \"<=2.0.0\"),\n            array(\"<=  2.0.0\", \"<=2.0.0\"),\n            array(\"<    2.0.0\", \"<2.0.0-0\"),\n            array(\"<\t2.0.0\", \"<2.0.0-0\"),\n            array(\">=0.1.97\", \">=0.1.97\"),\n            array(\">=0.1.97\", \">=0.1.97\"),\n            array(\"0.1.20 || 1.2.4\", \"0.1.20||1.2.4\"),\n            array(\">=0.2.3 || <0.0.1\", \">=0.2.3||<0.0.1-0\"),\n            array(\">=0.2.3 || <0.0.1\", \">=0.2.3||<0.0.1-0\"),\n            array(\">=0.2.3 || <0.0.1\", \">=0.2.3||<0.0.1-0\"),\n            array(\"||\", \"||\"),\n            array(\"2.x.x\", \">=2.0.0-0 <3.0.0-0\"),\n            array(\"1.2.x\", \">=1.2.0-0 <1.3.0-0\"),\n            array(\"1.2.x || 2.x\", \">=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0\"),\n            array(\"x\", \"*\"),\n            array(\"2.*.*\", '>=2.0.0-0 <3.0.0-0'),\n            array(\"1.2.*\", '>=1.2.0-0 <1.3.0-0'),\n            array(\"1.2.* || 2.*\", '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'),\n            array(\"*\", \"*\"),\n            array(\"2\", \">=2.0.0-0 <3.0.0-0\"),\n            array(\"2.3\", \">=2.3.0-0 <2.4.0-0\"),\n            array(\"~2.4\", \">=2.4.0-0 <2.5.0-0\"),\n            array(\"~>3.2.1\", \">=3.2.1-0 <3.3.0-0\"),\n            array(\"~1\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\"~>1\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\"~> 1\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\"~1.0\", \">=1.0.0-0 <1.1.0-0\"),\n            array(\"~ 1.0\", \">=1.0.0-0 <1.1.0-0\"),\n            array(\"^0\", \">=0.0.0-0 <1.0.0-0\"),\n            array(\"^ 1\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\"^0.1\", \">=0.1.0-0 <0.2.0-0\"),\n            array(\"^1.0\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\"^1.2\", \">=1.2.0-0 <2.0.0-0\"),\n            array(\"^0.0.1\", \"=0.0.1\"),\n            array(\"^0.0.1-beta\", \"=0.0.1-beta\"),\n            array(\"^0.1.2\", \">=0.1.2-0 <0.2.0-0\"),\n            array(\"^1.2.3\", \">=1.2.3-0 <2.0.0-0\"),\n            array(\"^1.2.3-beta.4\", \">=1.2.3-beta.4 <2.0.0-0\"),\n            array(\"<1\", \"<1.0.0-0\"),\n            array(\"< 1\", \"<1.0.0-0\"),\n            array(\">=1\", \">=1.0.0-0\"),\n            array(\">= 1\", \">=1.0.0-0\"),\n            array(\"<1.2\", \"<1.2.0-0\"),\n            array(\"< 1.2\", \"<1.2.0-0\"),\n            array(\"1\", \">=1.0.0-0 <2.0.0-0\"),\n            array(\">01.02.03\", \">1.2.3\", true),\n            array(\">01.02.03\", null),\n            array(\"~1.2.3beta\", \">=1.2.3-beta <1.3.0-0\", true),\n            array(\"~1.2.3beta\", null),\n            array(\"^ 1.2 ^ 1\", \">=1.2.0-0 <2.0.0-0 >=1.0.0-0 <2.0.0-0\")\n        );\n        foreach ($compare as $set) {\n            $loose = isset($set[2]) && $set[2];\n\n            $this->assertEquals(SemVer\\G::validRange($set[0], $loose), $set[1]);\n        }\n    }\n\n    public function testStrictVsLoose()\n    {\n        $compare = array(\n            array('=1.2.3', '1.2.3'),\n            array('01.02.03', '1.2.3'),\n            array('1.2.3-beta.01', '1.2.3-beta.1'),\n            array('   =1.2.3', '1.2.3'),\n            array('1.2.3foo', '1.2.3-foo')\n        );\n\n        foreach ($compare as $set) {\n            $ex = false;\n            try {\n                new SemVer\\SemVer($set[0]);\n            } catch (\\Exception $e) {\n                $ex = true;\n            }\n            $this->assertTrue($ex,\n                \"%s > Creating version with loose version $set[0], without loose flag set should throw exception.\");\n\n            $vers = new SemVer\\SemVer($set[0], true);\n\n            $this->assertEquals($vers->version->valueOf(), $set[1],\n                \"%s > (new version($set[0], true))->getVersion() == $set[1]\");\n            $this->assertTrue(SemVer\\G::eq($set[0], $set[1], true), \"%s > eq($set[0], $set[1], true)\");\n\n            $ex = false;\n            try {\n                SemVer\\G::eq($set[0], $set[1]);\n            } catch (\\Exception $e) {\n                $ex = true;\n            }\n            $this->assertTrue($ex, \"%s > eq($set[0], $set[1]) should throw\");\n        }\n    }\n}\n"
  },
  {
    "path": "vendor/vierbergenlars/php-semver/tests/VersionTest.php",
    "content": "<?php\n\nnamespace vierbergenlars\\SemVer\\Tests;\n\nuse vierbergenlars\\SemVer;\n\nclass VersionTest extends \\PHPUnit_Framework_TestCase\n{\n    public function testKeepSimpleversion()\n    {\n        $t = array(\n            '1.0.0',\n            '2.0.0',\n            '1.0.1',\n            '1.3.2',\n            '1.02.0' => '1.2.0',\n            '0.2.5',\n            '01.2.6' => '1.2.6',\n            '2.0.03' => '2.0.3',\n            '0.0.0',\n        );\n        foreach ($t as $original => $result) {\n            if ( ! is_string($original)) {\n                $original = $result;\n            }\n            $v = new SemVer\\version($original, true);\n            $this->assertEquals($v->__toString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testKeepSimpleversionComparator()\n    {\n        $t = array(\n            '>1.0.0',\n            '>1.1.0',\n            '>1.2.3',\n            '>0.5.6',\n            '>0.025.6'  => '>0.25.6',\n            '>=1.0.0',\n            '>=1.2.0',\n            '>=1.4.5',\n            '>=0.9.3',\n            '>=05.3.6'  => '>=5.3.6',\n            '<2.0.0-0',\n            '<5.6.0-0',\n            '<2.3.5-0',\n            '<0.2.3-0',\n            '<0.2.05'   => '<0.2.5-0',\n            '<=7.0.0',\n            '<=1.3.0',\n            '<=1.4.3',\n            '<=0.2.6',\n            '<=00.05.6' => '<=0.5.6',\n        );\n        foreach ($t as $original => $result) {\n            if ( ! is_string($original)) {\n                $original = $result;\n            }\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testShortSimpleversion()\n    {\n        $t = array(\n            '1'   => '>=1.0.0-0 <2.0.0-0',\n            '1.2' => '>=1.2.0-0 <1.3.0-0',\n            '1.0' => '>=1.0.0-0 <1.1.0-0',\n            '501' => '>=501.0.0-0 <502.0.0-0',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testShortSimpleversionComparator()\n    {\n        $t = array(\n            '>1.0.0' => '>1.0.0',\n            '<2.0.0' => '<2.0.0-0',\n            '<=5.2'  => '<=5.2.0-0',\n            '>=3'    => '>=3.0.0-0',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testSimpleversionWildcard()\n    {\n        $t = array(\n            '1.x.x' => '>=1.0.0-0 <2.0.0-0',\n            '1.x'   => '>=1.0.0-0 <2.0.0-0',\n            '1.x.5' => '>=1.0.0-0 <2.0.0-0',\n            '3.x'   => '>=3.0.0-0 <4.0.0-0',\n            '1.X.X' => '>=1.0.0-0 <2.0.0-0',\n            '1.*.*' => '>=1.0.0-0 <2.0.0-0',\n            '2.X.x' => '>=2.0.0-0 <3.0.0-0',\n            '5.*.x' => '>=5.0.0-0 <6.0.0-0',\n            'x'     => '',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testSimpleversionRange()\n    {\n        $t = array(\n            '1.0.0 - 2.0.0' => '>=1.0.0 <=2.0.0',\n            '1.2.3 - 1.3.0' => '>=1.2.3 <=1.3.0',\n            '4.3.0 - 4.3.1' => '>=4.3.0 <=4.3.1',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testShortversionRange()\n    {\n        $t = array(\n            '1 - 2'     => '>=1.0.0-0 <3.0.0-0',\n            '1.2 - 2.1' => '>=1.2.0-0 <2.2.0-0',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testSpermies()\n    {\n        $t = array(\n            '~1'     => '>=1.0.0-0 <2.0.0-0',\n            '~2.3'   => '>=2.3.0-0 <2.4.0-0',\n            '~3.7.2' => '>=3.7.2-0 <3.8.0-0',\n            '~1.x'   => '>=1.0.0-0 <2.0.0-0',\n            '~1.2.x' => '>=1.2.0-0 <1.3.0-0',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testInvalidVersion()\n    {\n        $t = array(\n            '3.x2',\n            'xx',\n            '2.xx',\n            '**.2',\n            'Xx*',\n            '.2.2',\n            '1..2',\n            '1.5.6.x',\n            '1.5.6.7',\n        );\n        foreach ($t as $original) {\n            $ex = false;\n            try {\n                $v = new SemVer\\expression($original);\n            } catch (SemVer\\SemVerException $e) {\n                $ex = true;\n            }\n            $this->assertTrue($ex);\n        }\n    }\n\n    public function testComplexExpessions()\n    {\n        $t = array(\n            '1.x || 2.0 - 2.3 || >4.x.x'  => '>=1.0.0-0 <2.0.0-0||>=2.0.0-0 <2.4.0-0||>=5.0.0-0',\n            '2.0.x || 2.1 - 4 || 4 - 4.5' => '>=2.0.0-0 <2.1.0-0||>=2.1.0-0 <5.0.0-0||>=4.0.0-0 <4.6.0-0',\n        );\n        foreach ($t as $original => $result) {\n            $v = new SemVer\\expression($original, true);\n            $this->assertEquals($v->getString(), $result, '[' . $original . '] %s');\n        }\n    }\n\n    public function testSatisfiedBy()\n    {\n        $t = array(\n            '1.0.0'            => '1.0.0',\n            '1.2.3'            => '1.2.3',\n            '>=1.0.1'          => array('1.0.1', '1.0.2', '1.2.0', '2.0.0'),\n            '>=2'              => array('2.0.0', '2.0.1', '2.1.5', '3.0.0'),\n            '<=2.4'            => array('1.2.0', '2.0.0', '2.3.999999999999'),\n            '3.x'              => array('3.0.1', '3.2.0', '3.1.5'),\n            '1.5.6 - 2.3.4'    => array('1.5.6', '1.5.7', '1.6.0', '2.1.0', '2.3.0', '2.3.3', '2.3.4'),\n            '1 - 2 || >=2.0.5' => array('1.0.0', '2.1.0', '1.4.0', '1.0.2', '3.0.4', '2.0.6', '3.0.0'),\n            '>4.0.0 <=4.2.3'   => array('4.0.1', '4.1.2', '4.2.3', '4.1.0'),\n        );\n        foreach ($t as $range => $satisfies) {\n            $e = new SemVer\\expression($range, true);\n            if ( ! is_array($satisfies)) {\n                $satisfies = array($satisfies);\n            }\n            foreach ($satisfies as $version) {\n                $v = new SemVer\\version($version, true);\n                $this->assertTrue($e->satisfiedBy($v), '[' . $range . ' :: ' . $version . '] %s');\n                $this->assertTrue($v->satisfies($e), '[' . $range . ' :: ' . $version . '] %s');\n            }\n        }\n    }\n\n    public function testNotSatisfiedBy()\n    {\n        $t = array(\n            '1.0.0'                    => '1.0.1',\n            '1.2.3'                    => '2.0.0',\n            '<1.0.1'                   => array('1.0.1', '1.0.2', '1.2.0', '2.0.0'),\n            '<=2'                      => array('2.0.1', '2.1.5', '3.0.0'),\n            '>=2.4'                    => array('1.2.0', '2.0.0'),\n            '3.x'                      => array('1.0.0', '1.9.9', '2.999.9999', '4.0.0'),\n            '<1.5.6 || >=2.3.4 <3.0.0' => array('1.5.6', '1.5.7', '1.6.0', '2.1.0', '2.3.0', '2.3.3', '3.0.0', '3.2.1'),\n            '1.2.0 - 2.1.2'            => array('1.1.2', '2.2.0'),\n            '>4.0.0 <=4.2.3'           => array('4.0.0', '4.2.4', '4.5.0', '3.2.2'),\n        );\n        foreach ($t as $range => $satisfies) {\n            $e = new SemVer\\expression($range, true);\n            if ( ! is_array($satisfies)) {\n                $satisfies = array($satisfies);\n            }\n            foreach ($satisfies as $version) {\n                $v = new SemVer\\version($version, true);\n                $this->assertFalse($e->satisfiedBy($v), '[' . $range . ' :: ' . $version . '] %s');\n                $this->assertFalse($v->satisfies($e), '[' . $range . ' :: ' . $version . '] %s');\n            }\n        }\n    }\n\n    /**\n     * @dataProvider invalidSemanticVersionProvider\n     * @expectedException \\vierbergenlars\\SemVer\\SemVerException\n     */\n    public function testInvalidExpressionString($version)\n    {\n        new SemVer\\expression($version);\n    }\n\n    /**\n     * @dataProvider invalidSemanticVersionProvider\n     * @expectedException \\vierbergenlars\\SemVer\\SemVerException\n     */\n    public function testInvalidVersionString($version)\n    {\n        new SemVer\\version($version);\n    }\n\n    public function invalidSemanticVersionProvider()\n    {\n        return array(\n            array('ce16575adbf06e5771b4bb4d5ac9609a685c1504'),\n            array('faeih178.58498uinv-dibqo'),\n            array('1.2.vqosbie'),\n            array('vce16575adbf06e5771b4bb4d5ac9609a685.c1504'),\n        );\n    }\n\n    function testVersionFunctions()\n    {\n        $t = array(\n            '1.0.0-alpha'      => array('M' => 1, 'm' => 0, 'p' => 0, 'pr' => array('alpha'), 'b' => array()),\n            '1.0.0-alpha.1'    => array('M' => 1, 'm' => 0, 'p' => 0, 'pr' => array('alpha', 1), 'b' => array()),\n            '1.0.0-0.3.7'      => array('M' => 1, 'm' => 0, 'p' => 0, 'pr' => array(0, 3, 7), 'b' => array()),\n            '1.0.0-x.7.z.92'   => array('M' => 1, 'm' => 0, 'p' => 0, 'pr' => array('x', 7, 'z', 92), 'b' => array()),\n            '1.0.0-alpha+001'  => array('M' => 1, 'm' => 0, 'p' => 0, 'pr' => array('alpha'), 'b' => array('001')),\n            '1.2.3-alpha.2+02' => array('M' => 1, 'm' => 2, 'p' => 3, 'pr' => array('alpha', 2), 'b' => array('02')),\n            '1.2.3-a.3+02.5.a' => array(\n                'M'  => 1,\n                'm'  => 2,\n                'p'  => 3,\n                'pr' => array('a', 3),\n                'b'  => array('02', 5, 'a'),\n            ),\n\n        );\n        foreach ($t as $version => $parts) {\n            $v = new SemVer\\version($version);\n            $this->assertEquals($v->getMajor(), $parts['M']);\n            $this->assertEquals($v->getMinor(), $parts['m']);\n            $this->assertEquals($v->getPatch(), $parts['p']);\n            $this->assertEquals($v->getPrerelease(), $parts['pr']);\n            $this->assertEquals($v->getBuild(), $parts['b']);\n        }\n    }\n}\n"
  },
  {
    "path": "views/csrf.php",
    "content": "<input id=\"wp-frc-csrf\" type=\"hidden\" value=\"<?php echo wp_create_nonce(); ?>\">\n"
  },
  {
    "path": "views/frc-spider.php",
    "content": "<h3>历史更新:</h3>\n<ul>\n    <li><b>v2.4.4</b></li>\n    <li>官方指导、代码修正, 写法规范.</li>\n    <li>简单而又大量的优化.</li>\n    <li>修复oss图片上传相对地址选项，但站点根目录不是 wp-content 会出现的bug.</li>\n    <li><b>v2.4.3</b></li>\n    <li>修复关键词替换的BUG.</li>\n    <li><b>v2.4.2</b></li>\n    <li>修复新鼠友安装后无法保存配置Bug.</li>\n    <li><b>v2.4.1</b></li>\n    <li>数据表字段长度调整</li>\n    <li>代码精简</li>\n    <li><b>v2.4.0</b></li>\n    <li>新增关键词插入功能, 可设置一批关键词随机插入文章正文段落中. </li>\n    <li>修复一个分页的历史遗留bug, 可输出单页页码进行采集</li>\n    <li>分页采集改为一次可采集3页</li>\n    <li>优化了代码</li>\n    <li><b>v2.3.0</b></li>\n    <li>Optimization Absolute Url.</li>\n    <li>增加内容分页采集功能.</li>\n    <li><b>v2.2.6</b></li>\n    <li>Fix Auto Absolute Url Bug.</li>\n    <li><b>v2.2.5</b></li>\n    <li>修复bug,提升稳定性.</li>\n    <li><b>v2.2.3-4</b></li>\n    <li>修复自动发布自动tags/动态内容不生效.</li>\n    <li><b>v2.2.2</b></li>\n    <li>微信采集链接优化.</li>\n    <li><b>v2.2.1</b></li>\n    <li>修复新用户使用简书微信知乎异常bug.</li>\n    <li><b>v2.2.0</b></li>\n    <li>更新许许多多地方.</li>\n    <li><b>v2.1.0 2020年05月13日(值得纪念)</b></li>\n    <li>* 采集底层内存占用重构, 鼠友的福音</li>\n    <li>* 批量发布使用设置的发布状态</li>\n    <li><b>v2.0.7</b></li>\n    <li>* 一些小优化</li>\n    <li><b>v2.0.6</b></li>\n    <li>* 插件提升权限管理员才可操作</li>\n    <li>* 修复一个存在的bug, .</li>\n    <li><b>胖鼠采集V2.0.0~2.0.5</b></li>\n    <li>* 数据链接优化</li>\n    <li>* 优化插件速度，精简很多地方.</li>\n    <li>* 低版本数据库兼容</li>\n    <li>* 大数据量鼠优化升级步骤</li>\n    <li>* 采集图片路径优化/优化window主机附件无法查看</li>\n    <li>* 代码小版本迭代</li>\n    <li>* 数据入库优化代码，优化速度</li>\n    <li>* 批量删除细节优化</li>\n    <li>Todo: 增加删除采集文章是否删除图片 控制开关</li>\n    <li>Todo: 增加删除已发布的文章是否删除附件 控制开关</li>\n    <li>Todo: 云存储对接</li>\n        <li><b>2020年04月26日「胖鼠采集2.0」</b></li>\n        <li>* 胖鼠采集架构重组升级、新版本，新世界</li>\n        <li><a href=\"javascript:;\"><span id=\"todo—more-button\" style=\"color: blue;\">更多</span></a>...</li>\n        <div class=\"todo-more-show\" style=\"display:none\">\n            <li>* 定时采集、定时发布强化</li>\n            <li>* 数据中心升级为数据桶模式、可设置数据桶对应发布分类</li>\n            <li>* 自动标签强化，标签匹配英文不区分大小写, 后续继续优化</li>\n            <li>* 动态内容强化样式。新版只在尾部添加动态内容, 后续继续优化</li>\n            <li>* 新增标签添加网站内链、5.1日前赞赏过自动标签用户免费激活</li>\n            <li>* 采集 & 调试</li>\n            <li>* 增加采集知乎问答功能</li>\n            <li>* 微信、简书、列表、详情、分页采集增加 debugging 功能</li>\n            <li>* 点击采集、异常后、按钮延时优化，避免不必要的问题</li>\n            <li>* 采集实体字符转义一些问题</li>\n            <li>* 文章重复问题优化、目前为url验重、后续增加文章标题验证重复</li>\n            <li>* 图片本地化功能加强升级</li>\n            <li>* 分页采集加强升级</li>\n            <li>* debug 全新升级 debugging</li>\n            <li>* 采集Url格式化升级</li>\n            <li>* 优化列表采集点击锚点体验</li>\n            <li>* 接口结果统一优化</li>\n            <li>* 采集数据可删除、批量管理</li>\n            <li>* 数据桶全局统计数据，所有数据一手掌握</li>\n            <li>* 更多优化请自行品尝</li>\n            <li><b>2019年11月30日</b></li>\n            <li>Todo: 修复一个Link拼接Bug</li>\n            <li>Todo: 删除优化插件关键字</li>\n            <li><b>2019年9月19日</b></li>\n            <li>Todo: 简书规则升级</li>\n            <li><b>2019年9月4日</b></li>\n            <li>Todo: 优化了很多代码</li>\n            <li>Todo: 增加图片不本地化选项。(采集速度超快)</li>\n            <li>Todo: 可指定采集图片的属性。(对于某些js异步加载图片的站点很有效)</li>\n            <li><b>2019年6月12日</b></li>\n            <li>Todo: 优化一些地方</li>\n            <li><b>2019年5月19日</b></li>\n            <li>Todo: 优化 Dynamic Content 功能, 优化了取文字样式</li>\n            <li>Todo: 优化 Auto Tags 功能, 暂时去掉了标签追加链接功能, 有bug回头解决了再加</li>\n            <li>Todo: 数据中心弱网发布时间优化</li>\n            <li><b>2019年5月5日</b></li>\n            <li>Todo: 优化 Dynamic Content 功能</li>\n            <li>Todo: 优化 Auto Tags 功能</li>\n            <li>Todo: Auto Tags 功能 增加开关和一些优化</li>\n            <li><b>2019年5月4日(五一)</b></li>\n            <li>Todo: 新功能 Dynamic Content 文章自动添加动态内容</li>\n            <li>Todo: 代码优化</li>\n            <li><b>2019年5月3日(五一)</b></li>\n            <li>Todo: 新功能 Auto Tags 文章自动打Tag or 优化一些文案</li>\n            <li><b>2019年4月30日</b></li>\n            <li>Todo: ok 修复一个仅新鼠会出现bug</li>\n            <li><b>2019年4月29日（晚）</b></li>\n            <li>Todo: ok 文章滤重改为强滤重</li>\n            <li>Todo: ok 数据表增加一项字段</li>\n            <li>Todo: ok 一次发布最大数量增加到30</li>\n            <li><b>2019年4月23日（晚）</b></li>\n            <li>Todo: ok 优化 据个别鼠要求, 采集标题 增长为120个汉字</li>\n            <li>Todo: ok 优化 采集保存配置一点逻辑优化</li>\n            <li>Todo: ok 优化 文案优化</li>\n            <li><b>2019年4月15日</b></li>\n            <li>Todo: ok 优化 采集标题可能超过40个汉字长度 控制在40个字符之内 </li>\n            <li>Todo: ok 优化 下载图片可能会超时优化了连接时间 </li>\n            <li>Todo: ok 优化 一次发布很多篇, 极端情况可能图片超时问题 </li>\n            <li>Todo: ok 优化 发布文章个别情况可能出现报错, 捕获错误 </li>\n            <li>Todo: ok 优化 文章别名, 使用文章标题作为文章别名 </li>\n            <li>Todo: ok 新增 公告功能: 用于胖鼠紧急通知众鼠使用, 无风险。</li>\n            <li>Todo: ok 新增 微信增加 作者变量{author} 公众号名字变量{name} 简书增加作者变量{author}</li>\n            <li><b>2019年4月14日</b></li>\n            <li>Todo: ok 修复了 一个不影响大局的sql错误 </li>\n            <li><b>2019年4月14日</b></li>\n            <li>Todo: ok 修复了 微信 简书 采集失败bug </li>\n            <li>Todo: ok 群内热心鼠发现的问题 @x (大家给他点个赞) </li>\n            <li>Todo: ok 丰富了很多错误提示, 还改进了一些代码 </li>\n            <li><b>2019年4月14日</b></li>\n            <li>Todo: ok 胖鼠采集全新架构 1.8 版本正式上线  </li>\n            <li>Todo: ok 修复window主机用户采集微信图片 鼠友服务器CA证书验证不通过问题  </li>\n            <li>Todo: ok 修复window主机 路径 DIRECTORY_SEPARATOR 可能出现的bug  </li>\n            <li>Todo: ok 采集内核2.0。更快的采集速度。 (3.0规划已有。采集速度会超级超级快)  </li>\n            <li>Todo: ok 采集图片自动查找后缀算法优化  </li>\n            <li>Todo: ok 自动特色图片功能完成(仅对新爬文章生效)  </li>\n            <li>Todo: ok 图片加入媒体库功能(仅对新爬文章生效)  </li>\n            <li>Todo: ok 图片加入附件(仅对新爬文章生效)  </li>\n            <li>Todo: ok 发布时图片发布失败。补二次下载  </li>\n            <li>Todo: ok 早日进群, 解锁最新黑科技 </li>\n            <li>Todo: ok 鼠们给点力量, 要不然真的写不动了 <a href=\"https://www.fatrat.cn/bounty\" target=\"_blank\">赏</a> And <a href=\"https://wordpress.org/support/plugin/fat-rat-collect/reviews\" target=\"_blank\">赞</a> </li>\n            <li><b>2019年4月8日</b></li>\n            <li>Todo: ok 修复了几位鼠友用window服务器出现的图片路径乱码bug</li>\n            <li><b>2019年3月31日</b></li>\n            <li>Todo: ok 修复了简书图片bug</li>\n            <li>Todo: ok 数据中心增加数据统计功能</li>\n            <li><b>2019年3月8日</b></li>\n            <li>Todo: ok 冒泡</li>\n            <li><b>2019年2月25日</b></li>\n            <li>Todo: ok 修复群里一个鼠友采集图片失败的bug.</li>\n            <li>Todo: ok 升级群里鼠友采集的图片默认居中需求.</li>\n            <li><b>2019年2月15日</b></li>\n            <li>Todo: ok 胖鼠采集PHP v5.6 版本尝鲜版发布.</li>\n            <li>Todo: ok 优化一些文案.</li>\n            <li><b>2019年1月25日</b></li>\n            <li>Todo: ok 定时发布 (给鼠友增加开关）</li>\n            <li>Todo: ok 定时采集 (给鼠友增加开关）</li>\n            <li>Todo: ok 图片可设置使用 相对/绝对 路径. 站群/单站点/CDN可能要的需求 </li>\n            <li>Todo: ok 微信采集自定义内容(鼠友要求可增加来源)</li>\n            <li>Todo: ok 免责声明</li>\n            <li>Todo: ok 一些代码优化</li>\n            <li><b>2019年1月24日</b></li>\n            <li>Todo: ok 鼠友发现采集的微信视频无法播放BUG!</li>\n            <li><b>2019年1月22日</b></li>\n            <li>Todo: ok 微信 And 列表采集 图片 自动剔除多余属性 增加 Alt字段 值为title 更好的SEO!</li>\n            <li><b>2019年1月21日</b></li>\n            <li>Todo: ok 一个安全过滤误伤了鼠友. 已修复</li>\n            <li>Todo: ok 修正版本号</li>\n            <li><b>2019年1月20日晚0点</b></li>\n            <li>Todo: ok Php版本验证提示</li>\n            <li>Todo: ok 配置中心批量删除</li>\n            <li>Todo: ok 数据中心可能出现的一个notice错误</li>\n            <li>Todo: ok 数据发布,增加发布作者,文章状态.</li>\n            <li>Todo: ok 数据中心作者字段优化</li>\n            <li>Todo: ok 赞赏码</li>\n            <li><b>2019年1月15日</b></li>\n            <li>Todo: ok 帮助的a 标签跳转新开标签页</li>\n            <li>Todo: ok 增加自动发布tag页面</li>\n            <li>Todo: ok 新增加的文档的链接</li>\n            <li>Todo: ok 分页采集增加默认select</li>\n            <li>Todo: ok 修复自动爬去功能异常</li>\n            <li>Todo: ok Css Js样式 兼容了其他插件</li>\n            <li>Todo: ok 修复一个列表爬虫。由于目标站不统一。链接可能拼接错误bug</li>\n            <li><b>2019年1月13日晚11:28</b></li>\n            <li>Todo: ok 优化配置中心一个 notice 错误</li>\n            <li>Todo: ok 增加了数据批量删除</li>\n            <li>Todo: ok 增加数据批量发布</li>\n            <li>Todo: ok 文章增加发布分类</li>\n            <li>Todo: ok 使用权限增加作者 编辑 管理员</li>\n            <li><b>2019年1月3日晚10:30</b></li>\n            <li>Todo: ok 优化了详情爬虫, 增加了默认选项</li>\n            <li>Todo: ok 增加了几个采集配置 寻仙新闻 御龙在天新闻 心理咨询师新闻 直播吧详情 虎扑详情</li>\n            <li>Todo: ok 优化了前端错误提示</li>\n            <li>Todo: 有个个别网站 gbk 个别乱码问题/未解决。utf-8很稳定</li>\n            <li>Todo: 今天关闭了站群自动发布,自动发布什么时候再次开启?</li>\n            <li><b>2019年1月1日</b></li>\n            <li>Todo: 写图片地方优化</li>\n            <li>Todo: 列表爬取 button disabled (遗留)</li>\n            <li>Todo: 配置 发布列表页 鼠标移动到区域后 才显示选择</li>\n            <li>Todo: Add Log</li>\n            <li>Todo: ok 采集时是否增加采集作者?时间?</li>\n            <li>Todo: ok 发布时增加选择发布分类?发布人?等功能?</li>\n            <li>Todo: 给列表和详情 支持ajax页面爬取?</li>\n            <li>Todo: ok 内容中Img图片自动识别 图片属性src? data-src? 或者其他?</li>\n            <li>Todo: 增加简书 头条等其他和微信一样默认爬虫?</li>\n            <li>Todo: 多线程爬虫.爬虫速度优化..</li>\n            <li>Todo: 各种采集/页面 错误提示 更加丰富? 让用户看到所有错误.</li>\n            <li>Todo: ok 详情页面 访问路径判断是(相对/绝对)路径（紧急）</li>\n            <li>Todo: ok 教会用户会使用debug模式，在新建配置页下方</li>\n            <li>Todo: ok FAQ丰富一下.</li>\n            <li>Todo: ok 是否要模仿一些其他采集工具的小功能选项? 有必要吗?</li>\n            <li>Todo: 胖鼠和其他采集器不一样。不需要脱离wordpress 完美支持jquery语法。想采什么采什么。可以删除内容任何标签</li>\n            <li>Todo: 图片因为站群的原因, 目前整站使用相对路径。后期考虑让用户选择 相对/绝对路径.</li>\n            <li>Todo: 定时爬取已自动开启！ 一日两次（每次间隔12小时）第一次运行在你安装胖鼠的时候. (后期是优化用户可以自定义时间, 增加用户可控制开关)</li>\n            <li>Todo: 想看爬虫下次执行时间? 安装一个插件 Cron Manager 里面有两个 frc_ 开头的任务就是咱们的定时程序</li>\n            <li>Todo: ok 数据中心文章预览功能</li>\n            <li>Todo: ok 配置中心 配置删除功能</li>\n            <li>Todo: ok 各种操作的友好提示</li>\n            <li>Todo: ok 自定义详情配置</li>\n            <li>Todo: ok 优化一些前端体验</li>\n            <li>Todo: ok 优化掉了一个log表</li>\n            <li>Todo: ok 优化掉了服务端无数行代码</li>\n            <li>Todo: ok 发一个稳定版本 应该不会大改框架了</li>\n            <li>Todo: ...</li>\n        </div>\n    </ul>"
  },
  {
    "path": "views/release-type.php",
    "content": "<?php\n\n$release_type = [\n    'WordPress' => 'WordPress',\n    'LightSNS' => 'lightSNS主题',\n    '7b2' => '7b2主题',\n];\n\n$type_map = ['post' => '文章', 'page' => '页面', 'attachment' => '附件'];\n$post_type = collect(get_post_types(array(\n    'public' => true,\n)))->map(function ($type) use ($type_map){\n    return $type_map[$type]??$type;\n})->filter(function ($type){\n    return $type !== '附件';\n})->toArray();\n\n$extension_field = collect();\n$extension_field = $extension_field\n    ->merge(['WordPress' => $post_type])\n    ->merge(['LightSNS' => [\n        'words' => '动态',\n        'music' => '音乐',\n        'single' => '文章',\n        'video' => '视频',\n        'normal'=> '帖子',]])\n    ->merge(['7b2' => [\n        'post-style-1' => '样式一',\n        'post-style-2' => '样式二',\n        'post-style-3' => '样式三',\n        'post-style-4' => '样式四',\n        'post-style-5' => '样式五',\n    ]]);\n\nif (!isset($release->release_type)){\n    $release->release_type = 'WordPress';\n}\n\n?>\n<h5>支持发布选项:</h5>\n<select class=\"release_type\">\n    <?php foreach ($release_type as $val => $title){ ?>\n        <option <?php if (isset($release->release_type) && $val == $release->release_type) esc_attr_e('selected'); ?> value=\"<?php esc_attr_e($val); ?>\"><?php _e($title); ?></option>\n    <?php } ?>\n    <option disabled>更多联系我..</option>\n</select>\n<hr />\n\n<div class=\"release_type_change\" data-value=\"WordPress\" <?php if (isset($release->release_type) && $release->release_type != 'WordPress'){ esc_attr_e('style=\"display: none;\"'); } ?>>\n    <h5>设置发布类型:</h5>\n    <ul>\n        <?php foreach ($extension_field['WordPress'] as $type => $title){ ?>\n            <li><input type=\"radio\" name=\"WordPress_extension_field\" value=\"<?php esc_attr_e($type); ?>\" <?php if (isset($release->extension_field) && $type == $release->extension_field) esc_attr_e('checked'); ?>><?php _e($title); ?></li>\n        <?php } ?>\n    </ul>\n    <hr />\n</div>\n\n<div class=\"release_type_change\" data-value=\"LightSNS\" <?php if (isset($release->release_type) && $release->release_type != 'LightSNS'){ esc_attr_e('style=\"display: none;\"'); } ?>>\n    <h5>设置发布类型:</h5>\n    <ul>\n        <?php foreach ($extension_field['LightSNS'] as $type => $title){ ?>\n            <li><input type=\"radio\" name=\"LightSNS_extension_field\" value=\"<?php esc_attr_e($type); ?>\" <?php if (isset($release->extension_field) && $type == $release->extension_field) esc_attr_e('checked'); ?>><?php _e($title); ?></li>\n        <?php } ?>\n    </ul>\n    <hr />\n</div>\n\n<div class=\"release_type_change\" data-value=\"7b2\" <?php if (isset($release->release_type) && $release->release_type != '7b2'){ esc_attr_e('style=\"display: none;\"'); } ?>>\n    <h5>设置发布样式:</h5>\n    <p style=\"color: #CCCCCC\">设置7b2文章页显示样式</p>\n    <ul>\n        <?php foreach ($extension_field['7b2'] as $type => $title){ ?>\n            <li><input type=\"radio\" name=\"7b2_extension_field\" value=\"<?php esc_attr_e($type); ?>\" <?php if (isset($release->extension_field) && $type == $release->extension_field) esc_attr_e('checked'); ?>><?php _e($title); ?></li>\n        <?php } ?>\n    </ul>\n    <hr />\n</div>"
  },
  {
    "path": "views/todo.html",
    "content": "<h3>历史更新:</h3>\n<ul>\n    <li><b>v2.7.0</b></li>\n    <li>微信公众号历史文章采集</li>\n    <li>登陆网站 cookie 采集</li>\n    <li><b>v2.6.*</b></li>\n    <li>....</li>\n    <li><b>v2.6.1</b></li>\n    <li>修复采集列表或者分页的时候，被目标站防采集命中，会出现的采集数据的url不一致、但是数据的标题以及内容和源网站不一样，数据会重复的bug</li>\n    <li><b>v2.6.0</b></li>\n    <li>升级组件，兼容PHP8</li>\n    <li>修复数据桶分页数量bug</li>\n    <li>修复自动采集html展示问题</li>\n    <li>修复配置数量为5个无法编辑问题</li>\n    <li>优化文案</li>\n    <li>优化项目结构</li>\n    <li>使用composer自动加载</li>\n    <li><b>v2.5.2</b></li>\n    <li>修复关键词随机插入保存错误</li>\n    <li><b>v2.5.1</b></li>\n    <li>部分语法兼容php8</li>\n    <li>数据桶样式优化</li>\n    <li>配置中心文章正文添加头尾html反斜线bug</li>\n    <li><a href=\"javascript:;\"><span id=\"todo—more-button\" style=\"color: blue;\">更多</span></a>...</li>\n        <div class=\"todo-more-show\" style=\"display:none\">\n            <li><b>v2.5.0</b></li>\n            <li>升级 bootstrap.</li>\n            <li><b>v2.4.4</b></li>\n            <li>官方指导、代码修正, 写法规范.</li>\n            <li>简单而又大量的优化.</li>\n            <li>修复oss图片上传相对地址选项，但站点根目录不是 wp-content 会出现的bug.</li>\n            <li><b>v2.4.3</b></li>\n            <li>修复关键词替换的BUG.</li>\n            <li><b>v2.4.2</b></li>\n            <li>修复新鼠友安装后无法保存配置Bug.</li>\n            <li><b>v2.4.1</b></li>\n            <li>数据表字段长度调整</li>\n            <li>代码精简</li>\n            <li><b>v2.4.0</b></li>\n            <li>新增关键词插入功能, 可设置一批关键词随机插入文章正文段落中. </li>\n            <li>修复一个分页的历史遗留bug, 可输出单页页码进行采集</li>\n            <li>分页采集改为一次可采集3页</li>\n            <li>优化了代码</li>\n            <li><b>v2.3.0</b></li>\n            <li>Optimization Absolute Url.</li>\n            <li>增加内容分页采集功能.</li>\n            <li><b>v2.2.6</b></li>\n            <li>Fix Auto Absolute Url Bug.</li>\n            <li><b>v2.2.5</b></li>\n            <li>修复bug,提升稳定性.</li>\n            <li><b>v2.2.3-4</b></li>\n            <li>修复自动发布自动tags/动态内容不生效.</li>\n            <li><b>v2.2.2</b></li>\n            <li>微信采集链接优化.</li>\n            <li><b>v2.2.1</b></li>\n            <li>修复新用户使用简书微信知乎异常bug.</li>\n            <li><b>v2.2.0</b></li>\n            <li>更新许许多多地方.</li>\n            <li><b>v2.1.0 2020年05月13日(值得纪念)</b></li>\n            <li>* 采集底层内存占用重构, 鼠友的福音</li>\n            <li>* 批量发布使用设置的发布状态</li>\n            <li><b>v2.0.7</b></li>\n            <li>* 一些小优化</li>\n            <li><b>v2.0.6</b></li>\n            <li>* 插件提升权限管理员才可操作</li>\n            <li>* 修复一个存在的bug, .</li>\n            <li><b>胖鼠采集V2.0.0~2.0.5</b></li>\n            <li>* 数据链接优化</li>\n            <li>* 优化插件速度，精简很多地方.</li>\n            <li>* 低版本数据库兼容</li>\n            <li>* 大数据量鼠优化升级步骤</li>\n            <li>* 采集图片路径优化/优化window主机附件无法查看</li>\n            <li>* 代码小版本迭代</li>\n            <li>* 数据入库优化代码，优化速度</li>\n            <li>* 批量删除细节优化</li>\n            <li>Todo: 增加删除采集文章是否删除图片 控制开关</li>\n            <li>Todo: 增加删除已发布的文章是否删除附件 控制开关</li>\n            <li>Todo: 云存储对接</li>\n            <li><b>2020年04月26日「胖鼠采集2.0」</b></li>\n            <li>* 胖鼠采集架构重组升级、新版本，新世界</li>\n            <li>* 定时采集、定时发布强化</li>\n            <li>* 数据中心升级为数据桶模式、可设置数据桶对应发布分类</li>\n            <li>* 自动标签强化，标签匹配英文不区分大小写, 后续继续优化</li>\n            <li>* 动态内容强化样式。新版只在尾部添加动态内容, 后续继续优化</li>\n            <li>* 新增标签添加网站内链、5.1日前赞赏过自动标签用户免费激活</li>\n            <li>* 采集 & 调试</li>\n            <li>* 增加采集知乎问答功能</li>\n            <li>* 微信、简书、列表、详情、分页采集增加 debugging 功能</li>\n            <li>* 点击采集、异常后、按钮延时优化，避免不必要的问题</li>\n            <li>* 采集实体字符转义一些问题</li>\n            <li>* 文章重复问题优化、目前为url验重、后续增加文章标题验证重复</li>\n            <li>* 图片本地化功能加强升级</li>\n            <li>* 分页采集加强升级</li>\n            <li>* debug 全新升级 debugging</li>\n            <li>* 采集Url格式化升级</li>\n            <li>* 优化列表采集点击锚点体验</li>\n            <li>* 接口结果统一优化</li>\n            <li>* 采集数据可删除、批量管理</li>\n            <li>* 数据桶全局统计数据，所有数据一手掌握</li>\n            <li>* 更多优化请自行品尝</li>\n            <li><b>2019年11月30日</b></li>\n            <li>Todo: 修复一个Link拼接Bug</li>\n            <li>Todo: 删除优化插件关键字</li>\n            <li><b>2019年9月19日</b></li>\n            <li>Todo: 简书规则升级</li>\n            <li><b>2019年9月4日</b></li>\n            <li>Todo: 优化了很多代码</li>\n            <li>Todo: 增加图片不本地化选项。(采集速度超快)</li>\n            <li>Todo: 可指定采集图片的属性。(对于某些js异步加载图片的站点很有效)</li>\n            <li><b>2019年6月12日</b></li>\n            <li>Todo: 优化一些地方</li>\n            <li><b>2019年5月19日</b></li>\n            <li>Todo: 优化 Dynamic Content 功能, 优化了取文字样式</li>\n            <li>Todo: 优化 Auto Tags 功能, 暂时去掉了标签追加链接功能, 有bug回头解决了再加</li>\n            <li>Todo: 数据中心弱网发布时间优化</li>\n            <li><b>2019年5月5日</b></li>\n            <li>Todo: 优化 Dynamic Content 功能</li>\n            <li>Todo: 优化 Auto Tags 功能</li>\n            <li>Todo: Auto Tags 功能 增加开关和一些优化</li>\n            <li><b>2019年5月4日(五一)</b></li>\n            <li>Todo: 新功能 Dynamic Content 文章自动添加动态内容</li>\n            <li>Todo: 代码优化</li>\n            <li><b>2019年5月3日(五一)</b></li>\n            <li>Todo: 新功能 Auto Tags 文章自动打Tag or 优化一些文案</li>\n            <li><b>2019年4月30日</b></li>\n            <li>Todo: ok 修复一个仅新鼠会出现bug</li>\n            <li><b>2019年4月29日（晚）</b></li>\n            <li>Todo: ok 文章滤重改为强滤重</li>\n            <li>Todo: ok 数据表增加一项字段</li>\n            <li>Todo: ok 一次发布最大数量增加到30</li>\n            <li><b>2019年4月23日（晚）</b></li>\n            <li>Todo: ok 优化 据个别鼠要求, 采集标题 增长为120个汉字</li>\n            <li>Todo: ok 优化 采集保存配置一点逻辑优化</li>\n            <li>Todo: ok 优化 文案优化</li>\n            <li><b>2019年4月15日</b></li>\n            <li>Todo: ok 优化 采集标题可能超过40个汉字长度 控制在40个字符之内 </li>\n            <li>Todo: ok 优化 下载图片可能会超时优化了连接时间 </li>\n            <li>Todo: ok 优化 一次发布很多篇, 极端情况可能图片超时问题 </li>\n            <li>Todo: ok 优化 发布文章个别情况可能出现报错, 捕获错误 </li>\n            <li>Todo: ok 优化 文章别名, 使用文章标题作为文章别名 </li>\n            <li>Todo: ok 新增 公告功能: 用于胖鼠紧急通知众鼠使用, 无风险。</li>\n            <li>Todo: ok 新增 微信增加 作者变量{author} 公众号名字变量{name} 简书增加作者变量{author}</li>\n            <li><b>2019年4月14日</b></li>\n            <li>Todo: ok 修复了 一个不影响大局的sql错误 </li>\n            <li><b>2019年4月14日</b></li>\n            <li>Todo: ok 修复了 微信 简书 采集失败bug </li>\n            <li>Todo: ok 群内热心鼠发现的问题 @x (大家给他点个赞) </li>\n            <li>Todo: ok 丰富了很多错误提示, 还改进了一些代码 </li>\n            <li><b>2019年4月14日</b></li>\n            <li>Todo: ok 胖鼠采集全新架构 1.8 版本正式上线  </li>\n            <li>Todo: ok 修复window主机用户采集微信图片 鼠友服务器CA证书验证不通过问题  </li>\n            <li>Todo: ok 修复window主机 路径 DIRECTORY_SEPARATOR 可能出现的bug  </li>\n            <li>Todo: ok 采集内核2.0。更快的采集速度。 (3.0规划已有。采集速度会超级超级快)  </li>\n            <li>Todo: ok 采集图片自动查找后缀算法优化  </li>\n            <li>Todo: ok 自动特色图片功能完成(仅对新爬文章生效)  </li>\n            <li>Todo: ok 图片加入媒体库功能(仅对新爬文章生效)  </li>\n            <li>Todo: ok 图片加入附件(仅对新爬文章生效)  </li>\n            <li>Todo: ok 发布时图片发布失败。补二次下载  </li>\n            <li>Todo: ok 早日进群, 解锁最新黑科技 </li>\n            <li>Todo: ok 鼠们给点力量, 要不然真的写不动了 <a href=\"https://www.fatrat.cn/bounty\" target=\"_blank\">赏</a> And <a href=\"https://wordpress.org/support/plugin/fat-rat-collect/reviews\" target=\"_blank\">赞</a> </li>\n            <li><b>2019年4月8日</b></li>\n            <li>Todo: ok 修复了几位鼠友用window服务器出现的图片路径乱码bug</li>\n            <li><b>2019年3月31日</b></li>\n            <li>Todo: ok 修复了简书图片bug</li>\n            <li>Todo: ok 数据中心增加数据统计功能</li>\n            <li><b>2019年3月8日</b></li>\n            <li>Todo: ok 冒泡</li>\n            <li><b>2019年2月25日</b></li>\n            <li>Todo: ok 修复群里一个鼠友采集图片失败的bug.</li>\n            <li>Todo: ok 升级群里鼠友采集的图片默认居中需求.</li>\n            <li><b>2019年2月15日</b></li>\n            <li>Todo: ok 胖鼠采集PHP v5.6 版本尝鲜版发布.</li>\n            <li>Todo: ok 优化一些文案.</li>\n            <li><b>2019年1月25日</b></li>\n            <li>Todo: ok 定时发布 (给鼠友增加开关）</li>\n            <li>Todo: ok 定时采集 (给鼠友增加开关）</li>\n            <li>Todo: ok 图片可设置使用 相对/绝对 路径. 站群/单站点/CDN可能要的需求 </li>\n            <li>Todo: ok 微信采集自定义内容(鼠友要求可增加来源)</li>\n            <li>Todo: ok 免责声明</li>\n            <li>Todo: ok 一些代码优化</li>\n            <li><b>2019年1月24日</b></li>\n            <li>Todo: ok 鼠友发现采集的微信视频无法播放BUG!</li>\n            <li><b>2019年1月22日</b></li>\n            <li>Todo: ok 微信 And 列表采集 图片 自动剔除多余属性 增加 Alt字段 值为title 更好的SEO!</li>\n            <li><b>2019年1月21日</b></li>\n            <li>Todo: ok 一个安全过滤误伤了鼠友. 已修复</li>\n            <li>Todo: ok 修正版本号</li>\n            <li><b>2019年1月20日晚0点</b></li>\n            <li>Todo: ok Php版本验证提示</li>\n            <li>Todo: ok 配置中心批量删除</li>\n            <li>Todo: ok 数据中心可能出现的一个notice错误</li>\n            <li>Todo: ok 数据发布,增加发布作者,文章状态.</li>\n            <li>Todo: ok 数据中心作者字段优化</li>\n            <li>Todo: ok 赞赏码</li>\n            <li><b>2019年1月15日</b></li>\n            <li>Todo: ok 帮助的a 标签跳转新开标签页</li>\n            <li>Todo: ok 增加自动发布tag页面</li>\n            <li>Todo: ok 新增加的文档的链接</li>\n            <li>Todo: ok 分页采集增加默认select</li>\n            <li>Todo: ok 修复自动爬去功能异常</li>\n            <li>Todo: ok Css Js样式 兼容了其他插件</li>\n            <li>Todo: ok 修复一个列表爬虫。由于目标站不统一。链接可能拼接错误bug</li>\n            <li><b>2019年1月13日晚11:28</b></li>\n            <li>Todo: ok 优化配置中心一个 notice 错误</li>\n            <li>Todo: ok 增加了数据批量删除</li>\n            <li>Todo: ok 增加数据批量发布</li>\n            <li>Todo: ok 文章增加发布分类</li>\n            <li>Todo: ok 使用权限增加作者 编辑 管理员</li>\n            <li><b>2019年1月3日晚10:30</b></li>\n            <li>Todo: ok 优化了详情爬虫, 增加了默认选项</li>\n            <li>Todo: ok 增加了几个采集配置 寻仙新闻 御龙在天新闻 心理咨询师新闻 直播吧详情 虎扑详情</li>\n            <li>Todo: ok 优化了前端错误提示</li>\n            <li>Todo: 有个个别网站 gbk 个别乱码问题/未解决。utf-8很稳定</li>\n            <li>Todo: 今天关闭了站群自动发布,自动发布什么时候再次开启?</li>\n            <li><b>2019年1月1日</b></li>\n            <li>Todo: 写图片地方优化</li>\n            <li>Todo: 列表爬取 button disabled (遗留)</li>\n            <li>Todo: 配置 发布列表页 鼠标移动到区域后 才显示选择</li>\n            <li>Todo: Add Log</li>\n            <li>Todo: ok 采集时是否增加采集作者?时间?</li>\n            <li>Todo: ok 发布时增加选择发布分类?发布人?等功能?</li>\n            <li>Todo: 给列表和详情 支持ajax页面爬取?</li>\n            <li>Todo: ok 内容中Img图片自动识别 图片属性src? data-src? 或者其他?</li>\n            <li>Todo: 增加简书 头条等其他和微信一样默认爬虫?</li>\n            <li>Todo: 多线程爬虫.爬虫速度优化..</li>\n            <li>Todo: 各种采集/页面 错误提示 更加丰富? 让用户看到所有错误.</li>\n            <li>Todo: ok 详情页面 访问路径判断是(相对/绝对)路径（紧急）</li>\n            <li>Todo: ok 教会用户会使用debug模式，在新建配置页下方</li>\n            <li>Todo: ok FAQ丰富一下.</li>\n            <li>Todo: ok 是否要模仿一些其他采集工具的小功能选项? 有必要吗?</li>\n            <li>Todo: 胖鼠和其他采集器不一样。不需要脱离wordpress 完美支持jquery语法。想采什么采什么。可以删除内容任何标签</li>\n            <li>Todo: 图片因为站群的原因, 目前整站使用相对路径。后期考虑让用户选择 相对/绝对路径.</li>\n            <li>Todo: 定时爬取已自动开启！ 一日两次（每次间隔12小时）第一次运行在你安装胖鼠的时候. (后期是优化用户可以自定义时间, 增加用户可控制开关)</li>\n            <li>Todo: 想看爬虫下次执行时间? 安装一个插件 Cron Manager 里面有两个 frc_ 开头的任务就是咱们的定时程序</li>\n            <li>Todo: ok 数据中心文章预览功能</li>\n            <li>Todo: ok 配置中心 配置删除功能</li>\n            <li>Todo: ok 各种操作的友好提示</li>\n            <li>Todo: ok 自定义详情配置</li>\n            <li>Todo: ok 优化一些前端体验</li>\n            <li>Todo: ok 优化掉了一个log表</li>\n            <li>Todo: ok 优化掉了服务端无数行代码</li>\n            <li>Todo: ok 发一个稳定版本 应该不会大改框架了</li>\n            <li>Todo: ...</li>\n        </div>\n    </ul>"
  }
]